classdef testAuthoringTool_m < handle

    % Properties that correspond to app components
    properties (Access = public)
        MainFigure                      matlab.ui.Figure
        OptionMenu                      matlab.ui.container.Menu
        OpenConfigFileMenu              matlab.ui.container.Menu
        ColorThemeMenu                  matlab.ui.container.Menu
        LightThemeMenu                  matlab.ui.container.Menu
        DarkThemeMenu                   matlab.ui.container.Menu
        HelpMenu                        matlab.ui.container.Menu
        DocumentationMenu               matlab.ui.container.Menu
        AboutMenu                       matlab.ui.container.Menu
        OpenExcelInOutputButton         matlab.ui.control.Button
        SelectModelFirstLabel           matlab.ui.control.Label
        FontSizeSlider                  matlab.ui.control.Slider
        MessagesTextArea                matlab.ui.control.TextArea
        MessagesLabel                   matlab.ui.control.Label
        RequirementEditorButton         matlab.ui.control.Button
        MainTabGroup                    matlab.ui.container.TabGroup
        GenHarnessTab                   matlab.ui.container.Tab
        DefaultSampleTimeEditField      matlab.ui.control.NumericEditField
        DefaultSampleTimeLabel          matlab.ui.control.Label
        TopModelCheckBox                matlab.ui.control.CheckBox
        ModelTree                       matlab.ui.container.Tree
        DesignModelsNode                matlab.ui.container.TreeNode
        SelectModelUnderTestButton      matlab.ui.control.Button
        TSHarnessLabel                  matlab.ui.control.Label
        SEHarnessLabel                  matlab.ui.control.Label
        MUTLabel                        matlab.ui.control.Label
        ModelUnderTestLabel             matlab.ui.control.Label
        CreateHarnessPanel              matlab.ui.container.Panel
        CreateTestCaseTemplateButton    matlab.ui.control.Button
        CreateModelHarnessButton        matlab.ui.control.Button
        HarnessTypeGroup                matlab.ui.container.ButtonGroup
        BothHarnessRadioButton          matlab.ui.control.RadioButton
        TestSequenceRadioButton         matlab.ui.control.RadioButton
        SignalEditorRadioButton         matlab.ui.control.RadioButton
        OpenTSHarnessButton             matlab.ui.control.Button
        OpenSEHarnessButton             matlab.ui.control.Button
        OpenMUTButton                   matlab.ui.control.Button
        TSHarnessModelLabel             matlab.ui.control.Label
        SEHarnessModelLabel             matlab.ui.control.Label
        ImportTestTab                   matlab.ui.container.Tab
        ImportTestTabGroup              matlab.ui.container.TabGroup
        CreateRBTFileTab                matlab.ui.container.Tab
        RemoveAllTestCasesButton        matlab.ui.control.Button
        RemoveSelectedTestCaseButton    matlab.ui.control.Button
        ImportedTestCaseListBox         matlab.ui.control.ListBox
        ImportedTestCaseListLabel       matlab.ui.control.Label
        AuthorNameEditField             matlab.ui.control.EditField
        AuthorNameLabel                 matlab.ui.control.Label
        CreateTestFileButton            matlab.ui.control.Button
        DryRunTab                       matlab.ui.container.Tab
        EnableWritebackCheckBox         matlab.ui.control.CheckBox
        WriteBackDryRunResultButton     matlab.ui.control.Button
        DryRunSelectedCasesButton       matlab.ui.control.Button
        MoveAllLeftButton               matlab.ui.control.Button
        MoveAllRightButton              matlab.ui.control.Button
        MoveLeftButton                  matlab.ui.control.Button
        MoveRightButton                 matlab.ui.control.Button
        SelectedDryRunCasesListBox      matlab.ui.control.ListBox
        SelectedDryRunCasesLabel        matlab.ui.control.Label
        AvailableTestCasesListBox       matlab.ui.control.ListBox
        AvailableTestCasesLabel         matlab.ui.control.Label
        IgnoreDataTypeCheckBox          matlab.ui.control.CheckBox
        OpenExcelInOutputButton_DryRun  matlab.ui.control.Button
        OpenExcelInInputButton_DryRun   matlab.ui.control.Button
        WritebackModeDropDown           matlab.ui.control.DropDown
        OpenSignalEditorButton          matlab.ui.control.Button
        WritebackTestVectorsButton      matlab.ui.control.Button
        ImportAllTestFilesButton        matlab.ui.control.Button
        UpdateTestFileButton            matlab.ui.control.Button
        OpenExcelOutButton              matlab.ui.control.Button
        OpenExcelInButton               matlab.ui.control.Button
        ExcelFileListBox                matlab.ui.control.ListBox
        OpenExcelFolderButton           matlab.ui.control.Button
        ExcelFileListLabel              matlab.ui.control.Label
        VerifyLLRTab                    matlab.ui.container.Tab
        LLRCoverageLamp                 matlab.ui.control.Lamp
        LLRTestLamp                     matlab.ui.control.Lamp
        LLRReadyLamp                    matlab.ui.control.Lamp
        OpenLLRCoverageReportButton     matlab.ui.control.Button
        OpenLLRTestReportButton         matlab.ui.control.Button
        VerifyModelToHLRButton          matlab.ui.control.Button
        LLRVerificationAxes             matlab.ui.control.UIAxes
        GenLLTestTab                    matlab.ui.container.Tab
        OpenTestHarnessButton           matlab.ui.control.Button
        OpenTestFileButton              matlab.ui.control.Button
        MaxGenerationTimeEditField      matlab.ui.control.NumericEditField
        MaxGenerationTimeLabel          matlab.ui.control.Label
        RefreshCoverageButton           matlab.ui.control.Button
        GenTestReadyLamp                matlab.ui.control.Lamp
        GenTestCompleteLamp             matlab.ui.control.Lamp
        GenerateTestButton              matlab.ui.control.Button
        CurrentCoverageLabel            matlab.ui.control.Label
        ConfigureTestGenerationButton   matlab.ui.control.Button
        TestGenerationAxes              matlab.ui.control.UIAxes
        EOCtoHLRTab                     matlab.ui.container.Tab
        HLRCoverageLamp                 matlab.ui.control.Lamp
        HLRTestLamp                     matlab.ui.control.Lamp
        HLRReadyLamp                    matlab.ui.control.Lamp
        OpenHLRCoverageReportButton     matlab.ui.control.Button
        OpenHLRTestReportButton         matlab.ui.control.Button
        VerifyEOCToHLRButton            matlab.ui.control.Button
        HLRVerificationAxes             matlab.ui.control.UIAxes
        EOCtoLLRTab                     matlab.ui.container.Tab
        LLREOCCoverageLamp              matlab.ui.control.Lamp
        LLREOCTestLamp                  matlab.ui.control.Lamp
        LLREOCReadyLamp                 matlab.ui.control.Lamp
        OpenLLREOCCoverageReportButton  matlab.ui.control.Button
        OpenLLREOCTestReportButton      matlab.ui.control.Button
        VerifyEOCToLLRButton            matlab.ui.control.Button
        LLREOCVerificationAxes          matlab.ui.control.UIAxes
        MergeCoverageTab                matlab.ui.container.Tab
        OpenMergedSILCoverageButton     matlab.ui.control.Button
        OpenMergedMILCoverageButton     matlab.ui.control.Button
        MergeCodeCoverageButton         matlab.ui.control.Button
        MergeModelCoverageButton        matlab.ui.control.Button
        SILCoverageAxes                 matlab.ui.control.UIAxes
        MILCoverageAxes                 matlab.ui.control.UIAxes
        TestManagerButton               matlab.ui.control.Button
    end


    properties (Access = public)
        ts % testSession
        hc % harncess creater
        hu % harness updater
        tr % test runner
        as %
        userTestSuiteName = 'RequirementBaseTest'
        % assume instrumented only
        instrfolder = 'instrumented'
        instrfile = ' (instrumented)'
        instr = ' INSTR'
        % define tag names
        TagNames = {'Gen Harness','Author Test','HLR test','LLR Test','EOC to HLR','EOC to LLR','Merge Cov'}
        % font color（默认初始化为消息服务颜色，启动后由ThemeManager覆盖）
        errorFontColor = MessageService.COLOR_ERROR
        warnFontColor = MessageService.COLOR_WARNING
        successFontColor = MessageService.COLOR_SUCCESS
        generalFontColor = MessageService.COLOR_INFO
        % simulink project handle
        prjObj
    end

    properties (Access = private)
        themeManager ThemeManager
        logger LoggingService
        topPanel matlab.ui.container.Panel
        bottomPanel matlab.ui.container.Panel
        centerPanel matlab.ui.container.Panel
        messagePalette struct = struct()
        currentThemeName char = ''
    end

    methods (Access = private)

        function callBackEnding(app,msg,level)
            if nargin < 3 || isempty(level)
                if isstruct(msg) && isfield(msg,'level')
                    level = msg.level;
                else
                    level = MessageService.inferLevel(msg);
                end
            end

            level = char(level);

            if isstruct(msg) && all(isfield(msg,{'text','level'}))
                msgStruct = msg;
                msgStruct.level = char(msgStruct.level);
            else
                msgStruct = MessageService.create(msg,'Level',level,'Timestamp',true);
            end

            if isempty(app.MessagesTextArea) || ~isvalid(app.MessagesTextArea)
                if ~isempty(app.logger) && isvalid(app.logger)
                    app.logger.logWarning(MessageService.convertToChar(msgStruct.text));
                end
                return;
            end

            palette = app.messagePalette;
            msgLevelKey = lower(string(msgStruct.level));
            if isstruct(palette) && ~isempty(palette)
                msgLevelKey = char(msgLevelKey);
                if isfield(palette, msgLevelKey)
                    msgStruct.color = palette.(msgLevelKey);
                elseif isfield(palette,'general')
                    msgStruct.color = palette.general;
                end
            end

            if ~isempty(app.MessagesTextArea) && isvalid(app.MessagesTextArea)
                app.MessagesTextArea.FontColor = msgStruct.color;
            end

            logText = MessageService.convertToChar(msgStruct.text);
            msgStruct.text = logText;

            if iscell(app.MessagesTextArea.Value)
                existingText = strjoin(app.MessagesTextArea.Value,newline);
            else
                existingText = MessageService.convertToChar(app.MessagesTextArea.Value);
            end

            if isempty(existingText)
                combinedText = logText;
            else
                combinedText = MessageService.accumulate(existingText,logText);
            end

            lines = splitlines(string(combinedText));
            lines = cellstr(strtrim(lines));
            if isempty(lines)
                lines = {''};
            end
            app.MessagesTextArea.Value = lines;

            if ~isempty(app.logger) && isvalid(app.logger)
                switch lower(msgStruct.level)
                    case MessageService.LEVEL_ERROR
                        app.logger.logError(logText);
                    case MessageService.LEVEL_WARNING
                        app.logger.logWarning(logText);
                    case MessageService.LEVEL_SUCCESS
                        app.logger.logSuccess(logText);
                    otherwise
                        app.logger.logInfo(logText);
                end
            end

            figure(app.MainFigure);
        end

        function colorSet = applyTheme(app, themeAlias)
            if isempty(app.themeManager) || ~isvalid(app.themeManager)
                app.themeManager = ThemeManager();
            end

            if nargin < 2 || isempty(themeAlias)
                themeAlias = 'light';
            end

            try
                themeName = app.themeManager.validateThemeName(themeAlias);
                app.themeManager.applyTheme(app.MainFigure, themeName);
            catch ex
                rethrowTraceableMessage(ex,'Theme application failed');
            end

            app.currentThemeName = themeName;
            colorSet = app.getThemeColorSet(themeName);

            app.errorFontColor = colorSet.errorFontColor;
            app.warnFontColor = colorSet.warnFontColor;
            app.successFontColor = colorSet.successFontColor;
            app.generalFontColor = colorSet.generalFontColor;
            app.messagePalette = colorSet.messagePalette;

            if ~isempty(app.MessagesTextArea) && isvalid(app.MessagesTextArea)
                app.MessagesTextArea.FontColor = app.generalFontColor;
            end
        end

        function colorSet = getThemeColorSet(app, themeName)
            palette = app.themeManager.getMessagePalette(themeName);
            colorSet.errorFontColor = palette.error;
            colorSet.warnFontColor = palette.warning;
            colorSet.successFontColor = palette.success;
            colorSet.generalFontColor = palette.general;
            colorSet.messagePalette = palette;
        end

        function cb = createCallbackFcn(app, callback, includeEvent)
            if nargin < 3
                includeEvent = false;
            end
            if includeEvent
                cb = @(src,event) callback(app, event);
            else
                cb = @(src,event) callback(app);
            end
        end
        
        function [createHarnessConfig,newTestCaseFileSetting] = overrideHarnessQuest(app,type)
            try
                createHarnessConfig = app.ts.getDefaultCreateHarnessConfig;

                switch type
                    case 'TS'
                        askForTS();
                    case 'SE'
                        askForSE();
                    case 'both'
                        askForSE();
                        askForTS();
                end

                modelName = app.ts.ModelUnderTest;
                newTestCaseFileSetting = app.ts.getDefaultNewTestCaseFileSetting;
                newTestCaseFileSetting.InUseInputElementOnly = false;
                newTestCaseFileSetting.filePath = ProjectPathManager.getDirPath('HLR test cases',modelName);

                if app.ts.hasTSHarness || app.ts.hasSEHarness
                    answer = uiconfirm(app.MainFigure,...
                        'Do you want to override the existing Excel file?', ...
                        'Override exiting Excel?',...
                        'Options',{'Yes','No','Cancel'},...
                        'DefaultOption',1,'CancelOption',3);
                    if strcmp(answer,'Yes')
                        newTestCaseFileSetting.overrideIfDuplicated = true;
                    elseif strcmp(answer,'Cancel')
                        error('User cancelled.')
                    else
                        newTestCaseFileSetting.overrideIfDuplicated = false;
                    end
                end

                createHarnessConfig.defaultDT = app.DefaultSampleTimeEditField.Value;
                createHarnessConfig.harnessPath = ProjectPathManager.getDirPath('HLR test cases',modelName);

            catch ex
                rethrowTraceableMessage(ex,'See below');
            end

            function askForTS()
                if app.ts.hasTSHarness
                    answer = uiconfirm(app.MainFigure,...
                        'There is already a test sequence harness model exist for model selected, do you want to override?', ...
                        'Override exiting external harness model?', ...
                        'Options',{'Yes','No, don''t create for this model','Cancel'},...
                        'DefaultOption',1,'CancelOption',3);
                else
                    answer = 'No';
                end
                if strcmp(answer,'Yes')
                    createHarnessConfig.overrideTS = true;
                elseif strcmp(answer,'Cancel')
                    error('User cancelled.')
                else
                    createHarnessConfig.overrideTS = false;
                end
            end
            function askForSE()
                if app.ts.hasSEHarness
                    answer = uiconfirm(app.MainFigure,...
                        'There is already a signal editor harness model exist for model selected, do you want to override?', ...
                        'Override exiting external harness model?', ...
                        'Options',{'Yes','No, don''t create for this model','Cancel'},...
                        'DefaultOption',1,'CancelOption',3);
                else
                    answer = 'No';
                end
                if strcmp(answer,'Yes')
                    createHarnessConfig.overrideSE = true;
                elseif strcmp(answer,'Cancel')
                    error('User cancelled.')
                else
                    createHarnessConfig.overrideSE = false;
                end
            end
        end

        function msg = setExcelInOpDirectly(app,previousMsg)
                config = get_session_config;
                modelName = app.ts.ModelUnderTest;
                testVectorFileName = [modelName config.TestFileSuffix config.TestCaseFileType];
                
                % 构建完整路径 - 基于第3条规则使用ProjectPathManager
                testCasesDir = ProjectPathManager.getDirPath('HLR test cases', modelName);
                fullPathToExcel = fullfile(testCasesDir, testVectorFileName);
                
                for i = 1:numel(app.ExcelFileListBox.Items)
                    app.ts.rmTestCaseFile(app.ExcelFileListBox.Items{i});
                end
                if exist(fullPathToExcel,"file")
                    % add Excel to project
                    if addFile2proj(app.prjObj,fullPathToExcel)
                        newMsg = [testVectorFileName ' added to project.'];
                        previousMsg = accumulate_msg(previousMsg,newMsg); 
                    end
                    msgAddTestFile = app.ts.addTestCaseFile(fullPathToExcel);
                else
                    msgAddTestFile = '';
                end
                msg = accumulate_msg(previousMsg,msgAddTestFile);
                if ~isempty(app.ts.getTestCaseFileNameList)
                    items = getFileName(app.ts.getTestCaseFileNameList);
                    if ischar(items)
                        items = {items};
                    end
                    app.ExcelFileListBox.Items = items;
                    desiredValue = app.ts.getCurrentExcelInOp;
                    % 基于规则第2条：确保比较的是同样的格式（都是文件名）
                    if ~isempty(desiredValue)
                        % 如果 desiredValue 是完整路径，提取文件名
                        [~, desiredName, desiredExt] = fileparts(desiredValue);
                        desiredFileName = [desiredName, desiredExt];
                    else
                        desiredFileName = '';
                    end
                    if ~isempty(desiredFileName) && any(strcmp(items, desiredFileName))
                        app.ExcelFileListBox.Value = desiredFileName;
                    else
                        if ~isempty(desiredFileName)
                            warnMsg = sprintf('Warning: Excel list selection "%s" was not found in available items while loading model "%s". setExcelInOpDirectly used the first available item instead.', desiredFileName, modelName);
                            msg = accumulate_msg(msg, warnMsg);
                            if ~isempty(app.logger) && isvalid(app.logger)
                                app.logger.logWarning(warnMsg);
                            end
                        end
                        if ~isempty(items)
                            app.ExcelFileListBox.Value = items{1};
                        else
                            app.ExcelFileListBox.Value = '';
                        end
                    end
                else
                    app.ExcelFileListBox.Items = {''};
                    app.ExcelFileListBox.Value = '';
                end
        end

        function setModelDir(app)
            modelName = app.ts.ModelUnderTest;
            app.ts.setRootDir(ProjectPathManager.getDirPath('HLR test cases',modelName));
            app.ts.setSessionDir('TestSession_HLR');
            app.tr.setTestFileName(ProjectNamingManager.getNameStr('HLR test cases',modelName))
        end

        function checkMILStatus(app)
            % check if test file exist
            if exist(which([app.tr.TestFileName '.mldatx']),"file")
                app.LLRReadyLamp.Color = 'green';
            else
                app.LLRReadyLamp.Color = 'black';
            end
            modelName = app.ts.ModelUnderTest;
            % check if test report exist
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            testRptPath = getRptPath('HLR sim report', modelName);
            if exist(testRptPath,"file")
                app.OpenLLRTestReportButton.Enable = true;
                app.LLRTestLamp.Color = 'green';
            else
                app.OpenLLRTestReportButton.Enable = false;
                app.LLRTestLamp.Color = 'black';
            end
            % check if coverage report exist
            covRptPath = fullfile(ProjectPathManager.getDirPath('HLR model coverage',modelName),...
                [ProjectNamingManager.getNameStr('HLR model coverage report',modelName),'.html']);
            if exist(covRptPath,"file")
                app.OpenLLRCoverageReportButton.Enable = true;
                app.LLRCoverageLamp.Color = 'green';
            else
                app.OpenLLRCoverageReportButton.Enable = false;
                app.LLRCoverageLamp.Color = 'black';
            end
        end

        function checkSILStatus(app)
            % check if test file exist
            if exist(which([app.tr.TestFileName '.mldatx']),"file")
                app.HLRReadyLamp.Color = 'green';
            else
                app.HLRReadyLamp.Color = 'black';
            end
            modelName = app.ts.ModelUnderTest;
            
            % check if test report exist
            testDir = fullfile(ProjectPathManager.getDirPath('HLR SIL results', modelName), app.instrfolder);
            covDir = ProjectPathManager.getDirPath('HLR SIL coverage', modelName);
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            rptFile = getRptPath('HLR SIL report', modelName);
            if exist(rptFile,"file")
                app.OpenHLRTestReportButton.Enable = true;
                app.HLRTestLamp.Color = 'green';
            else
                app.OpenHLRTestReportButton.Enable = false;
                app.HLRTestLamp.Color = 'black';
            end
            % check if coverage report exist
            covRptPath = fullfile(covDir,[ProjectNamingManager.getNameStr('HLR code coverage report',modelName),'.html']);
            if exist(covRptPath,"file")
                app.OpenHLRCoverageReportButton.Enable = true;
                app.HLRCoverageLamp.Color = 'green';
            else
                app.OpenHLRCoverageReportButton.Enable = false;
                app.HLRCoverageLamp.Color = 'black';
            end
        end

        function checkSIL_LL_Status(app)
            % check if test file exist
            if exist(which([app.tr.TestFileName '.mldatx']),"file")
                app.LLREOCReadyLamp.Color = 'green';
            else
                app.LLREOCReadyLamp.Color = 'black';
            end
            modelName = app.ts.ModelUnderTest;
            % check if test report exist
            testDir = fullfile(ProjectPathManager.getDirPath('LLR SIL results', modelName), app.instrfolder);
            covDir = ProjectPathManager.getDirPath('LLR SIL coverage', modelName);
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            rptFile = getRptPath('LLR SIL report', modelName);
            if exist(rptFile,"file")
                app.OpenLLREOCTestReportButton.Enable = true;
                app.LLREOCTestLamp.Color = 'green';
            else
                app.OpenLLREOCTestReportButton.Enable = false;
                app.LLREOCTestLamp.Color = 'black';
            end
            % check if coverage report exist
            covRptPath = fullfile(covDir,[ProjectNamingManager.getNameStr('LLR code coverage report',modelName),'.html']);
            if exist(covRptPath,"file")
                app.OpenLLREOCCoverageReportButton.Enable = true;
                app.LLREOCCoverageLamp.Color = 'green';
            else
                app.OpenLLREOCCoverageReportButton.Enable = false;
                app.LLREOCCoverageLamp.Color = 'black';
            end
        end

        function refreshMILPiechart(app)
            modelName = app.ts.ModelUnderTest;
            resultFile = fullfile(ProjectPathManager.getDirPath('HLR sim results',modelName),...
                [ProjectNamingManager.getNameStr('HLR sim results',modelName),'.mldatx']);
            if exist(resultFile,"file")
                resultObjs = sltest.testmanager.importResults(resultFile);
                result = [resultObjs.NumPassed,...
                    resultObjs.NumFailed,...
                    resultObjs.NumDisabled,...
                    resultObjs.NumIncomplete];
            else
                result = zeros(1,4);
            end
            plotPieChart(app.LLRVerificationAxes,result,app.generalFontColor)
        end

        function refreshSILPiechart(app)
            modelName = app.ts.ModelUnderTest;
            testDir = fullfile(ProjectPathManager.getDirPath('HLR SIL results', modelName), app.instrfolder);
            resultFile = fullfile(testDir, [ProjectNamingManager.getNameStr(['HLR SIL results', app.instrfile], modelName), '.mldatx']);
            if exist(resultFile,"file")
            resultObjs = sltest.testmanager.importResults(resultFile);
            result = [resultObjs.NumPassed,...
                resultObjs.NumFailed,...
                resultObjs.NumDisabled,...
                resultObjs.NumIncomplete];
            else
                result = zeros(1,4);
            end
            plotPieChart(app.HLRVerificationAxes,result,app.generalFontColor)
        end

        function refreshSIL_LL_Piechart(app)
            modelName = app.ts.ModelUnderTest;
            testDir = fullfile(ProjectPathManager.getDirPath('LLR SIL results', modelName), app.instrfolder);
            resultFile = fullfile(testDir, [ProjectNamingManager.getNameStr(['LLR SIL results', app.instrfile], modelName), '.mldatx']);
            if exist(resultFile,"file")
            resultObjs = sltest.testmanager.importResults(resultFile);
            result = [resultObjs.NumPassed,...
                resultObjs.NumFailed,...
                resultObjs.NumDisabled,...
                resultObjs.NumIncomplete];
            else
                result = zeros(1,4);
            end
            plotPieChart(app.LLREOCVerificationAxes,result,app.generalFontColor)
        end

        function ret = diagNoModel(app,varargin)
            if nargin > 1
                showAlert = false;
            else
                showAlert = true;
            end
            ret = true;
            if ~ismember(app.SelectModelFirstLabel.Text,getModelList())
                if showAlert
                    uialert(app.MainFigure,...
                        'Please select model first.','MBD Platform',...
                        Icon='info');
                end
                ret = false;
            end
        end

        function refreshSETCList(app)
            verboseTestCaseList = app.ts.getTestCaseList('verbose');
            if ~isempty(verboseTestCaseList)
            SEcases = verboseTestCaseList{verboseTestCaseList.TCType == TCTypes.SignalEditor,'TestCaseName'};
            app.WritebackModeDropDown.Items = SEcases;
            end
        end

        function coverage = collectCovData(app)
            warning off
            modelName = app.ts.ModelUnderTest;
            cvtFile = fullfile(ProjectPathManager.getDirPath('HLR model coverage', modelName), ...
                [ProjectNamingManager.getNameStr('HLR model coverage', modelName), '.cvt']);
            if ~exist(cvtFile,"file")
                coverage = [];
                return
            end
            [~,savedData] = cvload(cvtFile);
            savedData = savedData{1};
            % executioninfo — Execution coverage
            cov = executioninfo(savedData, modelName);
            if isempty(cov)
                coverage.execution_cov = [];
            else
                coverage.execution_cov = 100 * cov(1) / cov(2);
            end
            % conditioninfo — Condition coverage
            cov = conditioninfo(savedData, modelName);
            if isempty(cov)
                coverage.condition_cov = [];
            else
                coverage.condition_cov = 100 * cov(1) / cov(2);
            end
            % decisioninfo — Decision coverage
            cov = decisioninfo(savedData, modelName);
            if isempty(cov)
                coverage.decision_cov = [];
            else
                coverage.decision_cov = 100 * cov(1) / cov(2);
            end
            % mcdcinfo — Modified condition decision coverage (MCDC)
            cov = mcdcinfo(savedData, modelName);
            if isempty(cov)
                coverage.mcdc_cov = [];
            else
                coverage.mcdc_cov = 100 * cov(1) / cov(2);
            end
            warning on
        end

        function refreshLLTestGenLight(app)
            modelName = app.ts.ModelUnderTest;
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            testGenRptFile = getRptPath('test generation report', modelName);
            if exist(testGenRptFile,"file")
                app.GenTestCompleteLamp.Color = 'green';
            else
                app.GenTestCompleteLamp.Color = 'black';
            end
            % check test case status
            testfileName = fullfile(ProjectPathManager.getDirPath('LLR test cases', modelName),...
                [ProjectNamingManager.getNameStr('LLR test cases', modelName), '.mldatx']);
            if exist(testfileName,"file")
                app.GenTestReadyLamp.Color = 'green';
            else
                app.GenTestReadyLamp.Color = 'black';
            end
        end
    
        function barPlot(app,axis,value,label)
            if ~iscell(label)
                label = cell(label);
            end
            % remove those of empty values
            j=0;
            for i = 1:numel(label)
                if ~isempty(value{i})
                    j = j + 1;
                    Y(j) = round(value{i},1);
                    newlabel{j} = label{i};
                end
            end
            X = categorical(newlabel);
%             X = reordercats(X,newlabel);
            barObj = bar(axis,X,Y);
            xtips1 = barObj.XEndPoints;
            ytips1 = barObj.YEndPoints;
            cat = string(barObj.XData);
            sep = " : ";
            val = string(barObj.YData);
            labels = cat + sep + val;
            text(axis,xtips1,ytips1,labels,'HorizontalAlignment','center',...
                'VerticalAlignment','bottom',Color = app.generalFontColor)
        end

        function noCase = refreshTCsList(app)
            testCaseList = app.ts.getTestCaseList();
            if ~isempty(testCaseList)
                if iscell(testCaseList)
                    app.AvailableTestCasesListBox.Items = testCaseList;
                else
                    app.AvailableTestCasesListBox.Items = {testCaseList};
                end
                noCase = false;
            else
                noCase = true;
                app.AvailableTestCasesListBox.Items= {'List all cases'};
            end
            app.ImportedTestCaseListBox.Items = ...
                app.AvailableTestCasesListBox.Items;
            % refresh signal editor drop down items to dispaly all imported SE cases.
            app.refreshSETCList();
        end

        function reSetClass(app)
            app.ts = UnitTestSession();
            app.hc = HarnessCreator(app.ts);
            app.hu = HarnessUpdater(app.ts);
            app.tr = TestRunner(app.ts);
            app.as = StaticAnalyser(app.ts);
        end

        function loadBarPlotData(app,UIAxes,matFile)
            cla(UIAxes)
            if exist(matFile, 'file')
                covVal = load(matFile);
                if covVal.ExecutionCollected
                    value{1} = covVal.ExecutionOutcome*100;
                end
                if covVal.ConditionCollected
                    value{2} = covVal.ConditionOutcome*100;
                end
                if covVal.DecisionCollected
                    value{3} = covVal.DecisionOutcome*100;
                end
                if covVal.MCDCCollected
                    value{4} = covVal.MCDCOutcome*100;
                else
                    value{4} = [];
                end
                label{1} = 'ex';
                label{2} = 'cc';
                label{3} = 'dc';
                label{4} = 'mcdc';
                app.barPlot(UIAxes,value,label);
            end
        end
    end


    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
            d = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Starting up test authoring tool...', 'Indeterminate','on');
            
            % 基于第3条规则：自动检测 MATLAB 主题并应用
            % 尝试获取 MATLAB 的主题设置
            try
                s = settings;
                if s.matlab.desktop.currentTheme.PersonalValue == "dark"
                    defaultTheme = 'dark';
                else
                    defaultTheme = 'light';
                end
            catch
                % 如果获取失败，使用浅色主题作为默认
                defaultTheme = 'light';
            end
            
            colorSet = app.applyTheme(defaultTheme);
            app.messagePalette = colorSet.messagePalette;
            
            if isempty(app.logger) || ~isvalid(app.logger)
                app.logger = LoggingService.getInstance();
            end
            app.MessagesTextArea.FontColor = app.generalFontColor;
            app.ts = UnitTestSession();
            app.hc = HarnessCreator(app.ts);
            app.hu = HarnessUpdater(app.ts);
            app.tr = TestRunner(app.ts);
            app.as = StaticAnalyser(app.ts);
            try 
                uName = getpref('MBD_Platform','userName');
                if isempty(uName)
                    uName = getenv('username');
                end
                app.AuthorNameEditField.Value = uName;
            catch
                app.AuthorNameEditField.Value = getenv('username');
                addpref('MBD_Platform','userName',app.AuthorNameEditField.Value)
            end
            % set tag names
            app.GenHarnessTab.Title = app.TagNames{1};
            app.ImportTestTab.Title = app.TagNames{2};
            app.VerifyLLRTab.Title = app.TagNames{3};
            app.GenLLTestTab.Title = app.TagNames{4};
            app.EOCtoHLRTab.Title = app.TagNames{5};
            app.EOCtoLLRTab.Title = app.TagNames{6};
            app.MergeCoverageTab.Title = app.TagNames{7};
            refreshFolderTree(app.ModelTree);
            % get current project handle
            app.prjObj = currentProject;
            if ~isempty(app.logger) && isvalid(app.logger)
                app.logger.logInfo('testAuthoringTool启动完成');
            end
            close(d)
        end

        % Button pushed function: CreateModelHarnessButton
        function CreateModelHarnessButtonPushed(app, event)
            % ask user if they have loaded the model data
            if diagNoModel(app)
                dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                    'Message','Creating Model Harness...', 'Indeterminate','on');
                try
                    % create harness based on user selection
                    if app.SignalEditorRadioButton.Value
                        [createHarnessConfig,newTestCaseFileSetting] = overrideHarnessQuest(app,'SE');
                        msg = app.hc.createMdlHarness('SE',createHarnessConfig,newTestCaseFileSetting);
                    elseif app.TestSequenceRadioButton.Value
                        [createHarnessConfig,newTestCaseFileSetting] = overrideHarnessQuest(app,'TS');
                        msg = app.hc.createMdlHarness('TS',createHarnessConfig,newTestCaseFileSetting);
                    elseif app.BothHarnessRadioButton.Value
                        [createHarnessConfig,newTestCaseFileSetting] = overrideHarnessQuest(app,'both');
                        msg = app.hc.createMdlHarness('both',createHarnessConfig,newTestCaseFileSetting);
                    else
                        % do nothing for now.
                    end
                    app.MUTLabel.Text = app.ts.getMUT;
                    % 基于规则第3条：通过 ProjectPathManager 获取正确的路径
                    % harnessInfo.xml 应该和主模型在同一目录（specification），而不是在 test_cases
                    harnessLinker = [app.ts.ModelUnderTest '_harnessInfo.xml'];
                    harnessLinkerFullPath = fullfile(ProjectPathManager.getDirPath('model',app.ts.ModelUnderTest), harnessLinker);
                    % 基于规则第2条：先检查文件是否存在，避免silent error
                    if exist(harnessLinkerFullPath, 'file')
                        if addFile2proj(app.prjObj,harnessLinkerFullPath)
                            newMsg = [harnessLinker ' added to project path.'];
                            msg = accumulate_msg(msg,newMsg);
                        end
                    else
                        % 如果文件不存在，记录警告信息
                        newMsg = ['Warning: ' harnessLinker ' not found at expected location: ' harnessLinkerFullPath];
                        msg = accumulate_msg(msg,newMsg);
                    end
                    if app.ts.hasSEHarness
                        app.SEHarnessLabel.Text = app.ts.getSEHarness;
                        % 基于规则第3条：harness 模型在 test_cases/HLR 目录，需要使用完整路径
                        seHarnessFullPath = fullfile(ProjectPathManager.getDirPath('HLR test cases',app.ts.ModelUnderTest), app.SEHarnessLabel.Text);
                        if exist(seHarnessFullPath, 'file')
                            if addFile2proj(app.prjObj,seHarnessFullPath)
                                newMsg = [app.SEHarnessLabel.Text ' added to project path.'];
                                msg = accumulate_msg(msg,newMsg);
                            end
                        end
                        % Signal Editor Mat 文件也在同一目录
                        if ~isempty(app.hu.SignalEditorMatName)
                            % SignalEditorMatName 可能是完整路径或文件名，需要检查
                            [~, matFileName, matExt] = fileparts(app.hu.SignalEditorMatName);
                            matFileFullName = [matFileName matExt];
                            seMatFullPath = fullfile(ProjectPathManager.getDirPath('HLR test cases',app.ts.ModelUnderTest), matFileFullName);
                            if exist(seMatFullPath, 'file')
                                if addFile2proj(app.prjObj,seMatFullPath)
                                    newMsg = [matFileFullName ' added to project path.'];
                                    msg = accumulate_msg(msg,newMsg);
                                end
                            end
                        end
                    end
                    if app.ts.hasTSHarness
                        app.TSHarnessLabel.Text = app.ts.getTSHarness;
                        % 基于规则第3条：harness 模型在 test_cases/HLR 目录，需要使用完整路径
                        tsHarnessFullPath = fullfile(ProjectPathManager.getDirPath('HLR test cases',app.ts.ModelUnderTest), app.TSHarnessLabel.Text);
                        if exist(tsHarnessFullPath, 'file')
                            if addFile2proj(app.prjObj,tsHarnessFullPath)
                                newMsg = [app.TSHarnessLabel.Text ' added to project path.'];
                                msg = accumulate_msg(msg,newMsg);
                            end
                        end
                    end
                    % set excel in op directly
                    msg = app.setExcelInOpDirectly(msg);
                    % set session folder
                    app.setModelDir();
                    % refresh imported test case list
                    refreshTCsList(app);
                catch ME
                    if strcmp(ME.message,'User cancelled.')
                        msg = ME.message;
                    else
                        msg = ['Failed: ' ME.message];
                    end
                end
                close(dlg);
                callBackEnding(app,msg)
            end
        end

        % Button pushed function: ImportAllTestFilesButton
        function ImportAllTestFilesButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Updating harness...', 'Indeterminate','on');
            try
                msg = app.hu.importTestVector('TestCaseFile2Read','all');
                msgUpdate = app.hu.updateHarness();
                msg = accumulate_msg(msg,msgUpdate);
                msgPrep = app.tr.prepareFirstRun();
                msg = accumulate_msg(msg,msgPrep);
                app.AvailableTestCasesListBox.Items = app.ts.getTestCaseList();
                msgPrep = app.tr.prepareFirstRun();
                msg = accumulate_msg(msg,msgPrep);
            catch ex
                ex.message;
            end
            close(dlg);
            callBackEnding(app,msg)

        end

        % Button pushed function: UpdateTestFileButton
        function UpdateTestFileButtonPushed(app, event)
            if ~isempty(app.ExcelFileListBox.Value)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Updating harness...', 'Indeterminate','on');
            try
                % import Excel file to create test case pool
                msg = app.hu.importTestVector('TestCaseFile2Read',app.ExcelFileListBox.Value);

                % update harness model with test case pool
                msgUpdate = app.hu.updateHarness();
                msg = accumulate_msg(msg,msgUpdate);

                % set up test session folders
                msgPrep = app.tr.prepareFirstRun();
                msg = accumulate_msg(msg,msgPrep);

                refreshTCsList(app);
            catch ex
                msg = ex.message;
            end
            close(dlg);
            callBackEnding(app,msg)
            end
        end

        % Button pushed function: OpenSignalEditorButton
        function OpenSignalEditorButtonPushed(app, event)
            if app.diagNoModel
                try
                    signalEditor('DataSource', app.hu.SignalEditorMatName)
                catch
                    uialert(app.MainFigure,...
                        'Failed to open Signal Editor, is there a signal editor already open?','MBD Platform',...
                    Icon='warning');
                end
                figure(app.MainFigure);
            end
        end

        % Button pushed function: DryRunSelectedCasesButton
        function DryRunSelectedCasesButtonPushed(app, event)
            if diagNoModel(app)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Dry run tests...', 'Indeterminate','on');
            msgPrepare = app.tr.prepareFirstRun();
            if strcmp(app.SelectedDryRunCasesListBox.Items{1},'List selected case(s)')
                close(dlg)
                uialert(app.MainFigure,...
                    'Please select test cases for dry run.','MBD Platform',...
                    Icon='warning');
                return
            end
            [result,msgDryRun] = app.tr.dryRun(app.SelectedDryRunCasesListBox.Items);
            msg = accumulate_msg(msgPrepare,msgDryRun);
            if isempty(result) || any([result.nFailed,result.nDisabled,result.nIncomplete])
                msgFail = 'Failed: One or more test cases failed to run, please check details in Test Manager. If Excel is to be changed, please don''t forget to "Update TestCase".';
                msg = accumulate_msg(msg,msgFail);
            end
            callBackEnding(app,msg)
            close(dlg)
            end
        end

        % Button pushed function: TestManagerButton
        function TestManagerButtonPushed(app, event)
            try
                sltest.testmanager.clear;
                if strcmp(app.MainTabGroup.SelectedTab.Title,app.TagNames{2})
                    % if we are in dry run page, open dryrun test file
                    sltest.testmanager.load([app.SelectModelFirstLabel.Text,'_dryRun.mldatx']);
                else
                    if ~isempty(app.tr.TestFileName)
                        sltest.testmanager.load(app.tr.TestFileName);
                    end
                end
            catch ex
                callBackEnding(app,ex.message);
            end
            sltest.testmanager.view;
        end

        % Callback function
        function SaveSessionMenuSelected(app, event)
            defaultName = ['TestSession-' date '.mat'];
            [file,path] = uiputfile(defaultName,'Session File');
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Saving session data...', 'Indeterminate','on');
            if isnumeric(file)
                msg = 'User Cancelled Save.';
                callBackEnding(app,msg)
                close(dlg)
                return
            else
                filename = fullfile(path,file);
                % save to assigned mat file
                save(filename,'app.ts','app.hc','app.hu','app.tr','app.sa');
                msg = 'Session Saved.';
            end
            callBackEnding(app,msg)
            close(dlg)
        end

        % Callback function
        function LoadSessionMenuSelected(app, event)
            [FileName,Path] = uigetfile('*.mat','Please select the session file...');
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Loading session data...', 'Indeterminate','on');
%             [Obj,msg,app.SelectedDryRunCasesListBox.Items] = loadSession(FileName,Path);
%             if isnumeric(Obj)
%                 return
%             end
%             app.ts = Obj;
%             %
%             app.ModelUnderTestTextArea.Value = [app.ts.MUTpath,app.ts.MUT,'.slx'];
%             app.HarnessModelTextArea1.Value = [app.ts.TestPath, app.ts.SignalEditorHanressName, '.slx'];
%             app.HarnessModelTextArea2.Value = [app.ts.TestPath, app.ts.TestSequenceHanressName, '.slx'];
%             app.ExcelNameTextArea.Value = [app.ts.ExcelPath, app.ts.ExcelFileName, '.xlsx'];
%             app.AvailableTestCasesListBox.Items = app.ts.TCPool.TestCaseName;
%             app.WritebackModeDropDown.Items = app.ts.TCPool.TestCaseName;
%             callBackEnding(app,msg)
            close(dlg)
        end

        % Button pushed function: RequirementEditorButton
        function RequirementEditorButtonPushed(app, event)
            try
                slreq.editor
                msg = 'Requirement Editor opened.';
            catch
                msg = 'Failed to open Simulink Requirement Editor.';
            end
            callBackEnding(app,msg)
        end

        % Button pushed function: MoveRightButton
        function MoveRightButtonPushed(app, event)
            % 基于规则第2条：使用正确的 action 参数名称
            [app.AvailableTestCasesListBox.Items, app.SelectedDryRunCasesListBox.Items] = moveTCList('RightShift', ...
                app.AvailableTestCasesListBox.Items, app.AvailableTestCasesListBox.Value,...
                app.SelectedDryRunCasesListBox.Items, app.SelectedDryRunCasesListBox.Value);
        end

        % Button pushed function: MoveLeftButton
        function MoveLeftButtonPushed(app, event)
            % 基于规则第2条：使用正确的 action 参数名称
            [app.AvailableTestCasesListBox.Items, app.SelectedDryRunCasesListBox.Items] = moveTCList('LeftShift', ...
                app.AvailableTestCasesListBox.Items, app.AvailableTestCasesListBox.Value,...
                app.SelectedDryRunCasesListBox.Items, app.SelectedDryRunCasesListBox.Value);
        end

        % Button pushed function: MoveAllRightButton
        function MoveAllRightButtonPushed(app, event)
            % 基于规则第2条：使用正确的 action 参数名称
            [app.AvailableTestCasesListBox.Items, app.SelectedDryRunCasesListBox.Items] = moveTCList('RightShiftAll', ...
                app.AvailableTestCasesListBox.Items, app.AvailableTestCasesListBox.Value,...
                app.SelectedDryRunCasesListBox.Items, app.SelectedDryRunCasesListBox.Value);
        end

        % Button pushed function: MoveAllLeftButton
        function MoveAllLeftButtonPushed(app, event)
            % 基于规则第2条：使用正确的 action 参数名称
            [app.AvailableTestCasesListBox.Items, app.SelectedDryRunCasesListBox.Items] = moveTCList('LeftShiftAll', ...
                app.AvailableTestCasesListBox.Items, app.AvailableTestCasesListBox.Value,...
                app.SelectedDryRunCasesListBox.Items, app.SelectedDryRunCasesListBox.Value);
        end

        % Button pushed function: 
        % VerifyModelToHLRButton
        function VerifyModelToHLRButtonPushed(app, event)
            if diagNoModel(app)
                dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                    'Message','Running Functional (MIL) Test...', 'Indeterminate','on');
                try
                    modelName = app.ts.ModelUnderTest;
                    msg = '';
                    if ~exist(which([app.tr.TestFileName '.mldatx']),"file")
                        [msg,~] = app.tr.createTestFile('MIL',true,app.userTestSuiteName);
                        % 基于规则第3条：测试文件在 session 目录下，需要使用完整路径
                        testFileFullPath = fullfile(app.ts.getSessionDir, [app.tr.TestFileName '.mldatx']);
                        if exist(testFileFullPath, 'file')
                            if addFile2proj(app.prjObj,testFileFullPath)
                                newMsg = [app.tr.TestFileName '.mldatx added to project.'];
                                msg = accumulate_msg(msg,newMsg);
                            end
                        end
                    end
                    author = app.AuthorNameEditField.Value;
                    if app.TopModelCheckBox.Value
                        result = verifyModel2Reqs(modelName,'TreatAsTopMdl', author);
                    else
                        result = verifyModel2Reqs(modelName, [], author);
                    end
                    app.checkMILStatus();
                    msgDone = result.Message;
                    msg = accumulate_msg(msg,msgDone);
                    % get result from test result file
                    app.refreshMILPiechart;
                catch ex
                    msg = ex.message;
                end
                callBackEnding(app,msg)
                close(dlg);
            end
        end

        % Button pushed function: WritebackTestVectorsButton
        function WritebackTestVectorsButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Writing back test vector modifications to Excel','Indeterminate','on');
            try
                Excel2writeback = app.ExcelFileListBox.Value;
                TCName = app.WritebackModeDropDown.Value;
                regardlessOfMdlDT = app.IgnoreDataTypeCheckBox.Value;
                msg = app.hu.synchronizeTestVector(Excel2writeback,TCName,regardlessOfMdlDT);
            catch ex
                msg = ex.message;
            end
            callBackEnding(app,msg);
            close(dlg)
        end

        % Button pushed function: OpenExcelFolderButton
        function OpenExcelFolderButtonPushed(app, event)
            try
                winopen(app.ExcelFileListBox.Value)
                msg = 'Excel file opened.';
            catch
                msg = 'Failed to open Excel file, please verfy that the file exists.';
            end
            callBackEnding(app,msg);
        end

        % Button pushed function: SelectModelUnderTestButton
        function SelectModelUnderTestButtonPushed(app, event)
            if ~isempty(app.ModelTree.SelectedNodes)
            d = uiprogressdlg(app.MainFigure,'Title','Loading model harness','Indeterminate','on');
            try
                if ~isempty(app.ts.getSessionDir)
                    seesionDir = fullfile(app.ts.getSessionDir,'TestSession_HLR');
                    addFile2proj(app.prjObj,seesionDir,'IncludingChildFiles');
                    msgaddprj = [seesionDir ' added to project path.'];
                else
                    msgaddprj = [];
                end
                MdlFileName = app.ModelTree.SelectedNodes.Text;
                % reset class
                reSetClass(app)
                msg = app.ts.setModelUnderTest(MdlFileName);
                msg = accumulate_msg(msgaddprj,msg);
                app.MUTLabel.Text = app.ts.getMUT;
                if app.ts.hasSEHarness
                    app.SEHarnessLabel.Text = app.ts.getSEHarness;
                else
                    app.SEHarnessLabel.Text = '';
                end
                if app.ts.hasTSHarness
                    app.TSHarnessLabel.Text = app.ts.getTSHarness;
                else
                    app.TSHarnessLabel.Text = '';
                end
                config = app.ts.getDefaultCreateHarnessConfig;
                % display DT
                harnessDT = app.ts.getHarnessSampleTime;
                if isempty(harnessDT)
                    app.DefaultSampleTimeEditField.Value = config.defaultDT;
                else
                    app.DefaultSampleTimeEditField.Value = harnessDT;
                end
                msg = app.setExcelInOpDirectly(msg);
                % set root/session dir
                app.setModelDir()
                app.SelectModelFirstLabel.Text = MdlFileName;
                % reset dry run selection list box
                app.AvailableTestCasesListBox.Items = {'List all cases'};
                app.SelectedDryRunCasesListBox.Items = {'List selected case(s)'};
                % set top model check
                if ~strcmp(app.ModelTree.SelectedNodes.Text,'Design Models') && ...
                        strcmp(app.ModelTree.SelectedNodes.Parent.Text,'Design Models')
                    app.TopModelCheckBox.Value = true;
                else
                    app.TopModelCheckBox.Value = false;
                end
                % refresh imported test case list
                refreshTCsList(app);
            catch ME
                msg = ['Failed: ' ME.message];
            end
            close(d)
            callBackEnding(app,msg);
            else
                uialert(app.MainFigure,'Please select model first.','MBD Platform',...
                    Icon='info');
            end
        end

        % Button pushed function: openMUTButton
        function openMUTButtonPushed(app, event)
            if ~strcmp(app.MUTLabel.Text,'')
                try
                    open(app.MUTLabel.Text)
                catch ex
                    msg = ex.message;
                    callBackEnding(app,msg);
                end
            end
        end

        % Button pushed function: openSEHarnessButton
        function openSEHarnessButtonPushed(app, event)
            if ~strcmp(app.SEHarnessLabel.Text,'')
                try
                    open(app.SEHarnessLabel.Text)
                catch ex
                    msg = ex.message;
                    callBackEnding(app,msg);
                end
            end
        end

        % Button pushed function: openTSHarnessButton
        function openTSHarnessButtonPushed(app, event)
            if ~strcmp(app.TSHarnessLabel.Text,'')
                try
                    open(app.TSHarnessLabel.Text)
                catch ex
                    msg = ex.message;
                    callBackEnding(app,msg);
                end
            end
        end

        % Button pushed function: WriteBackDryRunResultButton
        function WriteBackDryRunResultButtonPushed(app, event)
            d = uiprogressdlg(app.MainFigure,'Title','Updating Excel',...
                'Message','Writting back simulation output as expected result for signal editor based test case...',...
                'Indeterminate','on');
            try
                msg = app.tr.writeBackExpectOutput(app.SelectedDryRunCasesListBox.Items,app.ExcelFileListBox.Value);
                uialert(app.MainFigure,...
                    'Please pay attention to and review/verify the auto-filled expected output value against requirements','Notice',...
                    'Icon','warning');
                app.EnableWritebackCheckBox.Value = false;
                app.WriteBackDryRunResultButton.Enable = false;
            catch ME
                msg = ['Error: ' ME.message];
            end
            callBackEnding(app,msg);
            close(d)
        end

        % Button pushed function: CreateTestCaseTemplateButton
        function CreateTestCaseTemplateButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Creating Excel test case template file...', 'Indeterminate','on');
            newTestCaseFileSetting = app.ts.getDefaultNewTestCaseFileSetting;
            modelName = app.ts.ModelUnderTest;
            newTestCaseFileSetting.filePath = ProjectPathManager.getDirPath('HLR test cases',modelName);
            if app.SignalEditorRadioButton.Value
                msg = app.hc.createTestCaseFileTemplate('SE',newTestCaseFileSetting)
            elseif app.TestSequenceRadioButton.Value
                msg = app.hc.createTestCaseFileTemplate('TS',newTestCaseFileSetting)
            elseif app.BothHarnessRadioButton.Value
                msg = app.hc.createTestCaseFileTemplate('both',newTestCaseFileSetting)
            else
                % do nothing for now.
            end
            callBackEnding(app,msg);
            close(d)
        end

        % Button pushed function: OpenTestReportButton
        function OpenTestReportButtonPushed2(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Opening Report...', 'Indeterminate','on');
            userMode = 'MIL';
            modelName = app.ts.ModelUnderTest;
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            rptFile = getRptPath('HLR sim report', modelName);
            if exist(rptFile,"file")
                open(rptFile);
                msg = [userMode ' test report opened.'];
                app.refreshMILPiechart;
            else
                msg = [userMode ' test report does not exist!'];
            end
            callBackEnding(app,msg);
            close(dlg)
        end

        % Button pushed function: OpenLLRCoverageReportButton
        function OpenLLRCoverageReportButtonPushed(app, event)
            userMode = 'MIL';
            modelName = app.ts.ModelUnderTest;
            rptFile = fullfile(ProjectPathManager.getDirPath('HLR model coverage',modelName),...
                [ProjectNamingManager.getNameStr('HLR model coverage report',modelName),'.html']);
            if exist(rptFile,"file")
                open(rptFile);
                app.refreshMILPiechart;
                msg = [userMode ' Coverage report opened.'];
            else
                msg = ['Warning: ' userMode ' Coverage report does not exist!'];
            end
            callBackEnding(app,msg);
        end

        % Callback function
        function RunXILTestButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Running SIL Test...', 'Indeterminate','on');
            if ~strcmp(app.AvailableTestCasesListBox.Items{1},'List all cases')
                LatestRst = runSILTest(app.ts,app.AvailableTestCasesListBox.Items,app.SILrptSwitch,app.SILtestSuiteSwitch);
                result = double(cell2mat(struct2cell(LatestRst)));
                plotPieChart(app.HLRVerificationAxes,result,app.generalFontColor)
                msg = 'SIL test complete.';
            else
                msg = 'Warning: Please first import a test case.';
            end
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function CreateBaselineButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Creating baseline...', 'Indeterminate','on');
            if ~strcmp(app.SelectedDryRunCasesListBox.Items{1},'List selected case(s)')
                LatestRst = runCreateBaseline(app.ts,app.SelectedDryRunCasesListBox.Items);
                result = double(cell2mat(struct2cell(LatestRst)));
                plotPieChart(app.MILCoverageAxes,result,app.generalFontColor)
                msg = 'Baseline Created.';
            else
                msg = 'Warning: Please first select a test case.';
            end
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function RunRegressionButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Running Regression Test...', 'Indeterminate','on');
            BLPath = app.ModelUnderTestTextArea_2.Value{1};
            LatestRst = runRegressionTest(app.ts,app.AvailableTestCasesListBox.Items,BLPath,app.RegressionRptSwitch,app.RegressionNewTestSuite);
            result = double(cell2mat(struct2cell(LatestRst)));
            plotPieChart(app.TestGenerationAxes,result,app.generalFontColor)
            close(dlg);
        end

        % Callback function
        function SelectBaselineFolderButtonPushed(app, event)
            BLPath = uigetdir('','Select a Baseline folder');
            if isnumeric(BLPath)
                msg = 'User cancel selection.';
            else
                app.ModelUnderTestTextArea_2.Value = BLPath;
                app.RunRegressionButton.Enable = true;
                msg = 'Baseline folder selected.';
            end
            callBackEnding(app,msg);
        end

        % Callback function
        function OpenXILReportButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Creating report...', 'Indeterminate','on');
            msg = openTestReport(app.ts, 'XILTestReport');
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function LoadModelDataButtonPushed(app, event)
            [dataFileList, filePath, ~] = uigetfile({'*.m;*.mat'},...
                'Select model data file(s) - If data is loaded, Cancel',...
                'MultiSelect', 'on');
            if isnumeric(dataFileList)
                msg = 'user cancelled.';
            else
                app.ts.loadDD(dataFileList)
            end
            callBackEnding(app,msg);
        end

        % Callback function
        function GenerateTestsButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Generating Coverage Tests...', 'Indeterminate','on');
            try
                genLowLevelTests(app.ts, 'IgnoreCovSatisfied', app.GenTextCheckBox.Value);
                msg = 'Coverage test generation complete.';
            catch ME
                msg = ['Error: ' ME.message];
            end
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function SelectBaselineStorageFolderButtonPushed(app, event)
            BLPath = uigetdir('','Select a Baseline Storage folder');
            if ~isnumeric(BLPath)
                app.ModelUnderTestTextArea_3.Value = BLPath;
                app.CreateBaselineButton.Enable = true;
                msg = 'BaseLine Folder Selected.';
            else
                msg = 'User cancel basedline folder selection.';
            end
            callBackEnding(app,msg);

        end

        % Callback function
        function OpenXILCovReportButtonPushed(app, event)
            msg = openTestReport(app.ts, 'XILCovReport');
            callBackEnding(app,msg);
        end

        % Callback function
        function OpenRegressionReportButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Creating Report...', 'Indeterminate','on');
            msg = openTestReport(app.ts, 'RegressionTestReport');
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function OpenRegressionCovReportButtonPushed(app, event)
            msg = openTestReport(app.ts, 'RegressionCovReport');
            callBackEnding(app,msg);
        end

        % Callback function
        function OpenTestReportButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Creating Report...', 'Indeterminate','on');
            if isequal(app.DropDown.Value,'MIL')
                msg = openTestReport(app.ts, 'LLR sim report');
            elseif isequal(app.DropDown.Value,'SIL')
                msg = openTestReport(app.ts, 'LLR SIL report');
            end
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function RefreshCovDataButtonPushed(app, event)
            reportPath = app.ts.TCResult.ReportFolder;
            cvtFile = [reportPath, '\FunctionTest\Coverage\', app.ts.MUT, '_Model_Coverage.cvt'];
            if exist(cvtFile,'file')
                app.CoveragedatafileEditField.Value = [app.ts.MUT, '_Model_Coverage.cvt'];
            end
        end

        % Callback function
        function GenTextCheckBoxValueChanged(app, event)
            value = app.GenTextCheckBox.Value;
            if value
                app.CoveragedatafileEditField.Enable = true;
                app.RefreshCovDataButton.Enable = true;
            else
                app.CoveragedatafileEditField.Enable = false;
                app.RefreshCovDataButton.Enable = false;
            end
        end

        % Callback function
        function RunTestsButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Running Generated Coverage Tests...', 'Indeterminate','on');
            if exist(fullfile(fileparts(app.ts.TestPath), 'Structural_Tests',[app.ts.MUT, '_SLDV_Based_Test.mldatx']), 'file')
                [msg, LatestRst] = runFormalTests(app.ts, app.DropDown.Value, app.GenerateReportSwitch_2.Value);
                if ~isempty(LatestRst)
                    result = double(cell2mat(struct2cell(LatestRst)));
                    plotPieChart(app.LLRVerificationAxes,result,app.generalFontColor);
                else
                    uialert(app.MainFigure,msg,'Warning',...
                        'Icon','warning');
                    result = [0;0;0;0];
                end
                plotPieChart(app.LLRVerificationAxes,result,app.generalFontColor);
            else
                msg = 'Test file is not existing';
            end
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function OpenCovReportButton_2Pushed(app, event)
            if isequal(app.DropDown.Value,'MIL')
                msg = openTestReport(app.ts, 'LLR model coverage report');
            elseif isequal(app.DropDown.Value,'SIL')
                msg = openTestReport(app.ts, 'LLR code coverage report');
            end
            callBackEnding(app,msg);
        end

        % Callback function
        function MergeModelCoverageButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Merging MIL Coverage Result...', 'Indeterminate','on');
            msg = mergeModelCoverage(app.ts);
            if strcmpi(msg,'ok')
                msg = 'MIL Coverage result merged.';
            else
                msg = ['Warning: ' msg];
            end
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function MergeCodeCoveargeButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Merging SIL Coverage Result...', 'Indeterminate','on');
            msg = mergeCodeCoverage(app.ts, 'SIL');
            if strcmpi(msg,'ok')
                msg = 'SIL Coverage result merged.';
            else
                msg = ['Warning: ' msg];
            end
            callBackEnding(app,msg);
            close(dlg);
        end

        % Callback function
        function OpenModelCovReportButtonPushed(app, event)
            msg = openTestReport(app.ts, 'Merged model coverage report');
            callBackEnding(app,msg);
        end

        % Callback function
        function OpenCodeCovReportButtonPushed(app, event)
            msg = openTestReport(app.ts, 'Merged code coverage report');
            callBackEnding(app,msg);
        end

        % Callback function
        function OpenSLDVHarnessButtonPushed(app, event)
            modelName = app.ts.MUT;
            harness = fullfile(fileparts(which(modelName)), ...
                [modelName, '_Harness_SLDV.slx']);
            if exist(harness, 'file')
                open_system(harness);
                msg = 'File opened.';
            else
                msg= 'Warning: File does not exist.';
            end
            callBackEnding(app,msg);
        end

        % Callback function
        function OpenTestGenRptButtonPushed(app, event)
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            % 注意：这里的代码使用了旧的硬编码路径，需要调整为使用modelName
            modelName = app.ts.MUT;
            rptFile = getRptPath('test generation report', modelName);
            if exist(rptFile,'file')
                open(rptFile);
                msg = 'File opened.';
            else
                msg= 'Warning: File does not exist.';
            end
            callBackEnding(app,msg);
        end

        % Close request function: MainFigure
        function MainFigureCloseRequest(app, event)
            sltest.testmanager.clearResults;
            try
                setpref('MBD_Platform','userName',app.AuthorNameEditField.Value)
                
                addFile2proj(app.prjObj,app.ts.getSessionDir,'IncludingChildFiles');
                
                % 基于第3条规则：正确关闭LoggingService
                if ~isempty(app.logger) && isvalid(app.logger)
                    app.logger.logInfo('testAuthoringTool正常关闭');
                end
            catch ex
                if ~isempty(app.logger) && isvalid(app.logger)
                    app.logger.logError(['关闭异常: ' ex.message]);
                end
                disp(ex.message)
            end
            delete(app)
        end

        % Value changed function: Enablewriteback
        function EnablewritebackValueChanged(app, event)
            app.WriteBackDryRunResultButton.Enable = app.EnableWritebackCheckBox.Value;
        end

        % Callback function
        function ReportabugMenuSelected(app, event)
            bugReporter;
        end

        % Value changed function: ListBox
        function ListBoxValueChanged(app, event)
            value = app.ExcelFileListBox.Value;
            msg = app.ts.setCurrentExcelInOp(value);
            callBackEnding(app,msg);
        end

        % Button pushed function: RemoveSelectedTestCaseButton
        function RemoveSelectedTestCaseButtonPushed(app, event)
            value = app.ExcelFileListBox.Value;
            msg = app.ts.rmTestCaseFile(value);
            app.ExcelFileListBox.Items = getFileName(app.ts.getTestCaseFileNameList);
            callBackEnding(app,msg);
        end

        % Button pushed function: OpenExcelInButton
        function OpenExcelInButtonPushed(app, event)
            [TestVectorFileName,TestVectorPath] = uigetfile('*.xlsx','Please select Excel file...');
            if isnumeric(TestVectorFileName)
                msg = 'User Cancelled Selection.';
                callBackEnding(app,msg)
                return
            end
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Importing test vectors & updating harness...', 'Indeterminate','on');
            try
                % 组合完整路径
                fullPathToExcel = fullfile(TestVectorPath, TestVectorFileName);
                msg = app.ts.addTestCaseFile(fullPathToExcel);
                app.ExcelFileListBox.Items = getFileName(app.ts.getTestCaseFileNameList);
                app.ExcelFileListBox.Value = app.ts.getCurrentExcelInOp;
            catch ME
                msg = ['Error: ' ME.message];
            end
            close(dlg)
            callBackEnding(app,msg)
        end

        % Button pushed function: VerifyEOCToHLRButton
        function VerifyEOCToHLRButtonPushed(app, event)
            try
                if app.diagNoModel()
                    dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                        'Message','Running Functional (SIL) Test...', 'Indeterminate','on');
                    modelName = app.ts.ModelUnderTest;
                    if ~exist(which([app.tr.TestFileName '.mldatx']),"file")
                        [msgCreateTestFile,~] = app.tr.createTestFile('MIL',true,app.userTestSuiteName);
                    else
                        msgCreateTestFile = '';
                    end
                    author = app.AuthorNameEditField.Value;
                    if app.TopModelCheckBox.Value
                        result = verifyObjCode2Reqs(modelName,'SIL',[],'TreatAsTopMdl', author);
                    else
                        result = verifyObjCode2Reqs(modelName,'SIL',[], [], author);
                    end
                    msg = accumulate_msg(msgCreateTestFile,result.Message);
                    app.checkSILStatus();
                    % get result from test result file
                    app.refreshSILPiechart;
                    close(dlg);
                else
                    return
                end
            catch ex
                msg = ex.message;
            end
            callBackEnding(app,msg)
        end

        % Button pushed function: OpenHLRTestReportButton
        function OpenHLRTestReportButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Opening Report...', 'Indeterminate','on');
            userMode = 'SIL';
            modelName = app.ts.ModelUnderTest;
            testDir = fullfile(ProjectPathManager.getDirPath('HLR SIL results', modelName), app.instrfolder);
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            rptFile = getRptPath('HLR SIL report', modelName);
            if exist(rptFile,"file")
                open(rptFile);
                app.refreshSILPiechart;
            else
                msg = [userMode ' test report does not exist!'];
                callBackEnding(app,msg);
            end
            close(dlg)
        end

        % Button pushed function: OpenHLRCoverageReportButton
        function OpenHLRCoverageReportButtonPushed(app, event)
            userMode = 'SIL';
            modelName = app.ts.ModelUnderTest;
            rptFile = fullfile(ProjectPathManager.getDirPath('HLR SIL coverage',modelName),...
                [ProjectNamingManager.getNameStr('HLR code coverage report',modelName),'.html']);
            if exist(rptFile,"file")
                open(rptFile);
                app.refreshMILPiechart;
                msg = [userMode ' Coverage report opened.'];
            else
                msg = ['Warning: ' userMode ' Coverage report does not exist!'];
            end
            callBackEnding(app,msg);
        end

        % Menu selected function: OpenConfigFileMenu
        function OpenConfigFileMenuSelected(app, event)
            d = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Opening configuration json file...', 'Indeterminate','on');
            uiopen('testSessionConfig.json',1)
            close(d)
        end

        % Callback function
        function reminderforloadDDMenuSelected(app, event)
            app.reminderforloadDDMenu.Checked = ~app.reminderforloadDDMenu.Checked;
        end

        % Menu selected function: AboutMenu
        function AboutMenuSelected(app, event)
            message = 'This tool is developed by MathWorks consulting. Verson:1.0.';
            uialert(app.MainFigure,message,'About this tool',...
                'Icon','info');
        end

        % Button pushed function: OpenExcelInOutputButton
        function OpenExcelInOutputButtonPushed(app, event)
            toWorkFolder
        end

        % Button pushed function: OpenExcelInInputButton_DryRun
        function OpenExcelInInputButton_DryRunPushed(app, event)
            if diagNoModel(app)
                mdlName = app.ts.ModelUnderTest;
                cd(ProjectPathManager.getDirPath('model root',mdlName))
            end
        end

        % Button pushed function: OpenExcelInOutputButton_DryRun
        function OpenExcelInOutputButton_DryRunPushed(app, event)
            if diagNoModel(app)
                mdlName = app.ts.ModelUnderTest;
                cd(ProjectPathManager.getDirPath('HLR test cases',mdlName))
            end
        end

        % Selection change function: TabGroup
        function TabGroupSelectionChanged(app, event)
            selectedTab = app.MainTabGroup.SelectedTab;
            switch selectedTab.Title
                case app.TagNames{3}
                    if diagNoModel(app,'noAlert')
                        app.checkMILStatus();
                        app.refreshMILPiechart;
                    end
                case app.TagNames{4}
                    cla(app.TestGenerationAxes);
                    if diagNoModel(app,'noAlert')
                        % show coverage bar plot
                        coverage = app.collectCovData();
                        if isempty(coverage)
                            return
                        end
                        value{1} = coverage.execution_cov;
                        value{2} = coverage.condition_cov;
                        value{3} = coverage.decision_cov;
                        value{4} = coverage.mcdc_cov;
                        label{1} = 'execution';
                        label{2} = 'condition';
                        label{3} = 'decision';
                        label{4} = 'mcdc';
                        app.barPlot(app.TestGenerationAxes,value,label);
                        % check report status
                        refreshLLTestGenLight(app)
                    end
                case app.TagNames{5}
                    if diagNoModel(app,'noAlert')
                        app.checkSILStatus();
                        app.refreshSILPiechart;
                    end
                case app.TagNames{6}
                    if diagNoModel(app,'noAlert')
                        app.checkSIL_LL_Status();
                        app.refreshSIL_LL_Piechart;
                    end
                case app.TagNames{7}
                    if diagNoModel(app,'noAlert')
                        % bar plot for merged model coverage
                        modelName = app.ts.ModelUnderTest;
                        covDir = ProjectPathManager.getDirPath('model coverage', modelName);
                        matFile = fullfile(covDir, [ProjectNamingManager.getNameStr('model coverage', modelName), '.mat']);
                        loadBarPlotData(app,app.MILCoverageAxes,matFile);
                        % bar plot for merged code coverage
                        covDir = ProjectPathManager.getDirPath('SIL coverage', modelName);
                        matFile = fullfile(covDir, [ProjectNamingManager.getNameStr('code coverage', modelName), '.mat']);
                        loadBarPlotData(app,app.SILCoverageAxes,matFile);
                    end
                otherwise
                    % do nothing...
            end
        end

        % Button pushed function: ConfigureTestGenerationButton
        function ConfigureTestGenerationButtonPushed(app, event)
            try
                if diagNoModel(app)
                    mdlName = app.ts.ModelUnderTest;
                    d = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                        'Message','Generating low level tests based on existing coverage data...', 'Indeterminate','on');
                    result = genLowLevelTests(mdlName, ...
                        'ModelCoverageObjectives', 'MCDC',...
                        'TestSuiteOptimization', 'Auto',...
                        'MaxProcessTime', app.MaxGenerationTimeEditField.Value,...
                        'AbsTol', 1e-6,...
                        'RelTol', 1e-3,...
                        'CI', false);
                    msg = result.Message;
                    refreshLLTestGenLight(app)
                    close(d)
                    else
                    return
                end
            catch ex
                msg = ex.message;
            end
            callBackEnding(app,msg);
        end

        % Button pushed function: GenerateTestButton
        function GenerateTestButtonPushed(app, event)
            try
                if diagNoModel(app)
                    d = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                        'Message','Verifying model to low level tests...', 'Indeterminate','on');
                    mdlName = app.ts.ModelUnderTest;
                    testfileName = fullfile(ProjectPathManager.getDirPath('LLR test cases', mdlName),...
                        [ProjectNamingManager.getNameStr('LLR test cases', mdlName), '.mldatx']);
                    if ~exist(testfileName,"file")
                        uialert(app.MainFigure,...
                            'Test file does not exist.','Test file does not exist',...
                            'Icon','warning');
                        return
                    end
                    author = app.AuthorNameEditField.Value;
                    if app.TopModelCheckBox.Value
                        result = verifyModel2LowLevelTests(mdlName,'TreatAsTopMdl',author);
                    else
                        result = verifyModel2LowLevelTests(mdlName,[],author);
                    end
                    msg = result.Message;
                    close(d)
                    else
                    return
                end
            catch ex
                msg = ex.message;
            end
            callBackEnding(app,msg);
        end

        % Button pushed function: OpenTestFileButton
        function OpenTestFileButtonPushed(app, event)
            % check report status
            modelName = app.ts.ModelUnderTest;
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            testGenRptFile = getRptPath('test generation report', modelName);
            if exist(testGenRptFile,"file")
                open(testGenRptFile);
            else
                uialert(app.MainFigure,...
                        'Test generation report does not exist.','File does not exist',...
                        'Icon','warning');
            end
        end

        % Button pushed function: VerifyEOCToLLRButton
        function VerifyEOCToLLRButtonPushed(app, event)
            if diagNoModel(app)
                try
                    d = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                        'Message','Verifying Object Code to Low Level Tests...', 'Indeterminate','on');
                    mdlName = app.ts.ModelUnderTest;
                    testfileName = fullfile(ProjectPathManager.getDirPath('LLR test cases', mdlName),...
                        [ProjectNamingManager.getNameStr('LLR test cases', mdlName), '.mldatx']);
                    if ~exist(testfileName,"file")
                        uialert(app.MainFigure,...
                            'Test file does not exist.','Test file does not exist',...
                            'Icon','warning');
                        return
                    end
                    author = app.AuthorNameEditField.Value;
                    if app.TopModelCheckBox.Value
                        result = verifyObjCode2LowLevelTests(mdlName,'SIL',[],'TreatAsTopMdl',author);
                    else
                        result = verifyObjCode2LowLevelTests(mdlName,'SIL',[],[],author);
                    end
                    app.checkSIL_LL_Status();
                    msg = result.Message;
                    % get result from test result file
                    app.refreshSIL_LL_Piechart;
                catch ex
                    msg = ex.message;
                end
                callBackEnding(app,msg)
                close(d);
            end
        end

        % Button pushed function: MergeModelCoverageButton
        function MergeModelCoverageButtonPushed2(app, event)
            if diagNoModel(app)
                try
                d = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                    'Message','Merging model coverage...', 'Indeterminate','on');
                mdlName = app.ts.ModelUnderTest;
                result = mergeModelCoverage(mdlName);
                msg = result.Message;
                % bar plot for merged model coverage
                modelName = app.ts.ModelUnderTest;
                covDir = ProjectPathManager.getDirPath('model coverage', modelName);
                matFile = fullfile(covDir, [ProjectNamingManager.getNameStr('model coverage', modelName), '.mat']);
                loadBarPlotData(app,app.MILCoverageAxes,matFile);
                catch ex
                    msg = ex.message;
                end
                callBackEnding(app,msg)
                close(d)
            end
        end

        % Button pushed function: MergeCodeCoverageButton
        function MergeCodeCoverageButtonPushed(app, event)
            if diagNoModel(app)
                try
                    d = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                        'Message','Merging code coverage...', 'Indeterminate','on');
                    modelName = app.ts.ModelUnderTest;
                    result = mergeCodeCoverage(modelName,'SIL');
                    msg = result.Message;
                    % bar plot for merged code coverage
                    covDir = ProjectPathManager.getDirPath('SIL coverage', modelName);
                    matFile = fullfile(covDir, [ProjectNamingManager.getNameStr('code coverage', modelName), '.mat']);
                    loadBarPlotData(app,app.SILCoverageAxes,matFile);
                    close(d)
                catch ex
                    msg = ex.message;
                end
                callBackEnding(app,msg)
            end
        end

        % Menu selected function: LightThemeMenu
        function LightThemeMenuSelected(app, event)
            colorSet = app.applyTheme('light');
            app.errorFontColor = colorSet.errorFontColor;
            app.warnFontColor = colorSet.warnFontColor;
            app.successFontColor = colorSet.successFontColor;
            app.generalFontColor = colorSet.generalFontColor;
            app.MessagesTextArea.FontColor = app.generalFontColor;
        end

        % Menu selected function: DarkThemeMenu
        function DarkThemeMenuSelected(app, event)
            colorSet = app.applyTheme('dark');
            app.errorFontColor = colorSet.errorFontColor;
            app.warnFontColor = colorSet.warnFontColor;
            app.successFontColor = colorSet.successFontColor;
            app.generalFontColor = colorSet.generalFontColor;
            app.MessagesTextArea.FontColor = app.generalFontColor;
        end

        % Button pushed function: createTestFileButton
        function createTestFileButtonPushed(app, event)
            if diagNoModel(app)
                try
                    dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                        'Message','Creating requirement based test testfile...', 'Indeterminate','on');
                    if isempty(app.ts.getSessionDir)
                        msg = 'Please first import an Excel test case file.';
                    else
                        [msg,~] = app.tr.createTestFile('MIL',true,app.userTestSuiteName);
                    end
                    % 基于规则第3条：测试文件在 session 目录下，需要使用完整路径
                    mldatxFullPath = fullfile(app.ts.getSessionDir, [app.tr.TestFileName '.mldatx']);
                    if exist(mldatxFullPath, 'file')
                        if addFile2proj(app.prjObj,mldatxFullPath)
                            newMsg = [app.tr.TestFileName '.mldatx added to project.'];
                            msg = accumulate_msg(msg,newMsg);
                        end
                    end
                    slmxFullPath = fullfile(app.ts.getSessionDir, [app.tr.TestFileName '.slmx']);
                    if exist(slmxFullPath, 'file')
                        if addFile2proj(app.prjObj,slmxFullPath)
                            newMsg = [app.tr.TestFileName '.slmx added to project.'];
                            msg = accumulate_msg(msg,newMsg);
                        end
                    end
                    % reset dryrun selection
                    app.SelectedDryRunCasesListBox.Items = {'List selected case(s)'};
                catch ex
                    msg = ex.message;
                end
                callBackEnding(app,msg);
                close(dlg)
            end
        end

        % Button pushed function: OpenLLREOCTestReportButton
        function OpenLLREOCTestReportButtonPushed(app, event)
            dlg = uiprogressdlg(app.MainFigure,'Title','Please Wait',...
                'Message','Opening Report...', 'Indeterminate','on');
            userMode = 'SIL';
            modelName = app.ts.ModelUnderTest;
            testDir = fullfile(ProjectPathManager.getDirPath('LLR SIL results', modelName), app.instrfolder);
            % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
            rptFile = getRptPath('LLR SIL report', modelName);
            if exist(rptFile,"file")
                open(rptFile);
                app.refreshSIL_LL_Piechart;
            else
                msg = [userMode ' test report does not exist!'];
                callBackEnding(app,msg);
            end
            close(dlg)
        end

        % Button pushed function: OpenLLREOCCoverageReportButton
        function OpenLLREOCCoverageReportButtonPushed(app, event)
            userMode = 'SIL';
            modelName = app.ts.ModelUnderTest;
            rptFile = fullfile(ProjectPathManager.getDirPath('LLR SIL coverage',modelName),...
                [ProjectNamingManager.getNameStr('LLR code coverage report',modelName),'.html']);
            if exist(rptFile,"file")
                open(rptFile);
                app.refreshMILPiechart;
                msg = [userMode ' Coverage report opened.'];
            else
                msg = ['Warning: ' userMode ' Coverage report does not exist!'];
            end
            callBackEnding(app,msg);
        end

        % Button pushed function: OpenMergedMILCoverageButton
        function OpenMergedMILCoverageButtonPushed(app, event)
            if diagNoModel(app)
                modelName = app.ts.ModelUnderTest;
                rptFile = fullfile(ProjectPathManager.getDirPath('model coverage',modelName),...
                    [ProjectNamingManager.getNameStr('model coverage report',modelName),'.html']);
                if exist(rptFile,"file")
                    open(rptFile);
                else
                    msg = ['Warning: Merged MIL Coverage report does not exist!'];
                    callBackEnding(app,msg);
                end
            end
        end

        % Button pushed function: OpenMergedSILCoverageButton
        function OpenMergedSILCoverageButtonPushed(app, event)
            if diagNoModel(app)
                modelName = app.ts.ModelUnderTest;
                rptFile = fullfile(ProjectPathManager.getDirPath('SIL coverage',modelName),...
                    [ProjectNamingManager.getNameStr('code coverage report',modelName),'.html']);
                if exist(rptFile,"file")
                    open(rptFile);
                else
                    msg = ['Warning: Merged Code Coverage report does not exist!'];
                    callBackEnding(app,msg);
                end
            end
        end

        % Value changed function: WritebackModeDropDown
        function WritebackModeDropDownValueChanged(app, event)
            value = app.WritebackModeDropDown.Value;
            
        end

        % Button pushed function: OpenTestHarnessButton
        function OpenTestHarnessButtonPushed(app, event)
            if app.diagNoModel
                userMode = 'MIL';
                modelName = app.ts.ModelUnderTest;
                % 基于规则第3条：使用getRptPath()从配置文件读取报告格式
                rptFile = getRptPath('LLR sim report', modelName);
                if exist(rptFile,"file")
                    open(rptFile);
                else
                    msg = [userMode ' low level test report does not exist!'];
                    uialert(app.MainFigure,msg,'MBD Platform',Icon='warning');
                end
            end
        end

        % Button pushed function: RefreshCoverageButton
        function RefreshCoverageButtonPushed(app, event)
            if app.diagNoModel
                userMode = 'MIL';
                modelName = app.ts.ModelUnderTest;
                rptFile = fullfile(ProjectPathManager.getDirPath('LLR model coverage',modelName),...
                    [ProjectNamingManager.getNameStr('LLR model coverage report',modelName),'.html']);
                if exist(rptFile,"file")
                    open(rptFile);
                else
                    msg = ['Warning: ' userMode ' low level test coverage report does not exist!'];
                    uialert(app.MainFigure,msg,'MBD Platform',Icon='warning');
                end
            end
        end

        % Menu selected function: HelpMenu_2
        function HelpMenu_2Selected(app, event)
            
        end

        % Button pushed function: RemoveSelectedTestCaseFromListButtonPushed
        % (Used for CreateRBTFileTab to remove test cases from list)
        function RemoveSelectedTestCaseFromListButtonPushed(app, event)
            TCs = app.AvailableTestCasesListBox.Value;
            if ~strcmp('List all cases',TCs)
                msg = app.ts.rmTestCase(TCs);
                callBackEnding(app,msg)
            end
            refreshTCsList(app);
        end

        % Button pushed function: RemoveAllTestCasesButton
        function RemoveAllTestCasesButtonPushed(app, event)
            TCs = app.AvailableTestCasesListBox.Items;
            if ~strcmp('List all cases',TCs{1})
                msg = app.ts.rmTestCase(TCs);
                callBackEnding(app,msg)
                app.SelectedDryRunCasesListBox.Items = {'List selected case(s)'};
            end
            refreshTCsList(app);
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create MainFigure and hide until all components are created
            app.MainFigure = uifigure('Visible', 'off');
            app.MainFigure.Position = [100 100 706 685];
            app.MainFigure.Name = 'MBD platform test auuthoring tool';
            app.MainFigure.Resize = 'off';
            app.MainFigure.CloseRequestFcn = app.createCallbackFcn(@MainFigureCloseRequest, true);
            app.MainFigure.Scrollable = 'on';

            % Create OptionMenu
            app.OptionMenu = uimenu(app.MainFigure);
            app.OptionMenu.Text = 'Option';

            % Create OpenConfigFileMenu
            app.OpenConfigFileMenu = uimenu(app.OptionMenu);
            app.OpenConfigFileMenu.MenuSelectedFcn = app.createCallbackFcn(@OpenConfigFileMenuSelected, true);
            app.OpenConfigFileMenu.Text = 'OpenConfigFile';

            % Create ColorThemeMenu
            app.ColorThemeMenu = uimenu(app.OptionMenu);
            app.ColorThemeMenu.Text = 'color theme';

            % Create light/dark theme menu items
            app.LightThemeMenu = uimenu(app.ColorThemeMenu);
            app.LightThemeMenu.MenuSelectedFcn = app.createCallbackFcn(@LightThemeMenuSelected, true);
            app.LightThemeMenu.Text = 'Light Theme';

            app.DarkThemeMenu = uimenu(app.ColorThemeMenu);
            app.DarkThemeMenu.MenuSelectedFcn = app.createCallbackFcn(@DarkThemeMenuSelected, true);
            app.DarkThemeMenu.Text = 'Dark Theme';

            % Create HelpMenu
            app.HelpMenu = uimenu(app.MainFigure);
            app.HelpMenu.Text = 'Help';

            % Create DocumentationMenu
            app.DocumentationMenu = uimenu(app.HelpMenu);
            app.DocumentationMenu.MenuSelectedFcn = app.createCallbackFcn(@HelpMenu_2Selected, true);
            app.DocumentationMenu.Text = 'Help';

            % Create AboutMenu
            app.AboutMenu = uimenu(app.HelpMenu);
            app.AboutMenu.MenuSelectedFcn = app.createCallbackFcn(@AboutMenuSelected, true);
            app.AboutMenu.Text = 'About';

            % Create TestManagerButton
            app.TestManagerButton = uibutton(app.MainFigure, 'push');
            app.TestManagerButton.ButtonPushedFcn = app.createCallbackFcn(@TestManagerButtonPushed, true);
            app.TestManagerButton.BackgroundColor = [0.2314 0.2314 0.2314];
            app.TestManagerButton.FontColor = [0.9294 0.6941 0.1255];
            app.TestManagerButton.Tooltip = {'打开Test Manager界面'};
            app.TestManagerButton.Position = [448 642 112 33];
            app.TestManagerButton.Text = 'Test Manager';

            % Create MainTabGroup
            app.MainTabGroup = uitabgroup(app.MainFigure);
            app.MainTabGroup.SelectionChangedFcn = app.createCallbackFcn(@TabGroupSelectionChanged, true);
            app.MainTabGroup.BusyAction = 'cancel';
            app.MainTabGroup.Position = [18 218 671 409];

            % Create GenHarnessTab
            app.GenHarnessTab = uitab(app.MainTabGroup);
            app.GenHarnessTab.Title = 'Gen Harness';

            % Create SEHarnessModelLabel
            app.SEHarnessModelLabel = uilabel(app.GenHarnessTab);
            app.SEHarnessModelLabel.HorizontalAlignment = 'center';
            app.SEHarnessModelLabel.FontWeight = 'bold';
            app.SEHarnessModelLabel.FontAngle = 'italic';
            app.SEHarnessModelLabel.FontColor = [0.9294 0.6941 0.1255];
            app.SEHarnessModelLabel.Position = [95 71 93 38];
            app.SEHarnessModelLabel.Text = {'Harness Model'; 'Signal Editor'};

            % Create TSHarnessModelLabel
            app.TSHarnessModelLabel = uilabel(app.GenHarnessTab);
            app.TSHarnessModelLabel.HorizontalAlignment = 'center';
            app.TSHarnessModelLabel.FontWeight = 'bold';
            app.TSHarnessModelLabel.FontAngle = 'italic';
            app.TSHarnessModelLabel.FontColor = [0.9294 0.6941 0.1255];
            app.TSHarnessModelLabel.Position = [95 11 93 38];
            app.TSHarnessModelLabel.Text = {'Harness Model'; 'Test Sequence'};

            % Create OpenMUTButton
            app.OpenMUTButton = uibutton(app.GenHarnessTab, 'push');
            app.OpenMUTButton.ButtonPushedFcn = app.createCallbackFcn(@openMUTButtonPushed, true);
            app.OpenMUTButton.BackgroundColor = [0.149 0.149 0.149];
            app.OpenMUTButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenMUTButton.Position = [36 140 41 23];
            app.OpenMUTButton.Text = 'open';

            % Create OpenSEHarnessButton
            app.OpenSEHarnessButton = uibutton(app.GenHarnessTab, 'push');
            app.OpenSEHarnessButton.ButtonPushedFcn = app.createCallbackFcn(@openSEHarnessButtonPushed, true);
            app.OpenSEHarnessButton.BackgroundColor = [0.149 0.149 0.149];
            app.OpenSEHarnessButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenSEHarnessButton.Position = [36 79 41 23];
            app.OpenSEHarnessButton.Text = 'open';

            % Create OpenTSHarnessButton
            app.OpenTSHarnessButton = uibutton(app.GenHarnessTab, 'push');
            app.OpenTSHarnessButton.ButtonPushedFcn = app.createCallbackFcn(@openTSHarnessButtonPushed, true);
            app.OpenTSHarnessButton.BackgroundColor = [0.149 0.149 0.149];
            app.OpenTSHarnessButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenTSHarnessButton.Position = [36 19 41 23];
            app.OpenTSHarnessButton.Text = 'open';

            % Create CreateHarnessPanel
            app.CreateHarnessPanel = uipanel(app.GenHarnessTab);
            app.CreateHarnessPanel.ForegroundColor = [0.9294 0.6941 0.1255];
            app.CreateHarnessPanel.TitlePosition = 'centertop';
            app.CreateHarnessPanel.Title = 'Create Harness';
            app.CreateHarnessPanel.BackgroundColor = [0 0 0];
            app.CreateHarnessPanel.Position = [472 189 184 188];

            % Create HarnessTypeGroup
            app.HarnessTypeGroup = uibuttongroup(app.CreateHarnessPanel);
            app.HarnessTypeGroup.Tooltip = {'选择创建基于Signal Editor的测试用例还是基于Test Sequence的测试用例，或者同时创建。'};
            app.HarnessTypeGroup.ForegroundColor = [1 1 1];
            app.HarnessTypeGroup.BorderType = 'none';
            app.HarnessTypeGroup.BackgroundColor = [0 0 0];
            app.HarnessTypeGroup.Position = [12 8 160 70];

            % Create SignalEditorRadioButton
            app.SignalEditorRadioButton = uiradiobutton(app.HarnessTypeGroup);
            app.SignalEditorRadioButton.Text = 'SignalEditor';
            app.SignalEditorRadioButton.FontColor = [0.651 0.651 0.651];
            app.SignalEditorRadioButton.Position = [8 42 87 22];
            app.SignalEditorRadioButton.Value = true;

            % Create TestSequenceRadioButton
            app.TestSequenceRadioButton = uiradiobutton(app.HarnessTypeGroup);
            app.TestSequenceRadioButton.Text = 'TestSequence';
            app.TestSequenceRadioButton.FontColor = [0.651 0.651 0.651];
            app.TestSequenceRadioButton.Position = [8 22 98 22];

            % Create BothHarnessRadioButton
            app.BothHarnessRadioButton = uiradiobutton(app.HarnessTypeGroup);
            app.BothHarnessRadioButton.Text = 'Both';
            app.BothHarnessRadioButton.FontWeight = 'bold';
            app.BothHarnessRadioButton.FontColor = [0.651 0.651 0.651];
            app.BothHarnessRadioButton.Position = [8 2 49 22];

            % Create CreateModelHarnessButton
            app.CreateModelHarnessButton = uibutton(app.CreateHarnessPanel, 'push');
            app.CreateModelHarnessButton.ButtonPushedFcn = app.createCallbackFcn(@CreateModelHarnessButtonPushed, true);
            app.CreateModelHarnessButton.BackgroundColor = [0.149 0.149 0.149];
            app.CreateModelHarnessButton.FontWeight = 'bold';
            app.CreateModelHarnessButton.FontColor = [0.9294 0.6941 0.1255];
            app.CreateModelHarnessButton.Tooltip = {'点击为待测单元模型创建harness模型'};
            app.CreateModelHarnessButton.Position = [12 128 160 40];
            app.CreateModelHarnessButton.Text = {'Create '; 'Model Harness'};

            % Create CreateTestCaseTemplateButton
            app.CreateTestCaseTemplateButton = uibutton(app.CreateHarnessPanel, 'push');
            app.CreateTestCaseTemplateButton.ButtonPushedFcn = app.createCallbackFcn(@CreateTestCaseTemplateButtonPushed, true);
            app.CreateTestCaseTemplateButton.BackgroundColor = [0.149 0.149 0.149];
            app.CreateTestCaseTemplateButton.FontColor = [0.651 0.651 0.651];
            app.CreateTestCaseTemplateButton.Enable = 'off';
            app.CreateTestCaseTemplateButton.Tooltip = {'创建一个新的Excel测试用例模板'};
            app.CreateTestCaseTemplateButton.Position = [12 90 160 30];
            app.CreateTestCaseTemplateButton.Text = 'Create Test Case Template';

            % Create ModelUnderTestLabel
            app.ModelUnderTestLabel = uilabel(app.GenHarnessTab);
            app.ModelUnderTestLabel.HorizontalAlignment = 'center';
            app.ModelUnderTestLabel.FontWeight = 'bold';
            app.ModelUnderTestLabel.FontAngle = 'italic';
            app.ModelUnderTestLabel.FontColor = [0.9294 0.6941 0.1255];
            app.ModelUnderTestLabel.Position = [95 132 93 38];
            app.ModelUnderTestLabel.Text = {'Model '; 'Under Test'};

            % Create MUTLabel
            app.MUTLabel = uilabel(app.GenHarnessTab);
            app.MUTLabel.WordWrap = 'on';
            app.MUTLabel.FontColor = [0.9294 0.6941 0.1255];
            app.MUTLabel.Position = [210 130 445 42];
            app.MUTLabel.Text = '';

            % Create SEHarnessLabel
            app.SEHarnessLabel = uilabel(app.GenHarnessTab);
            app.SEHarnessLabel.WordWrap = 'on';
            app.SEHarnessLabel.FontColor = [0.9294 0.6941 0.1255];
            app.SEHarnessLabel.Position = [207 69 448 42];
            app.SEHarnessLabel.Text = '';

            % Create TSHarnessLabel
            app.TSHarnessLabel = uilabel(app.GenHarnessTab);
            app.TSHarnessLabel.WordWrap = 'on';
            app.TSHarnessLabel.FontColor = [0.9294 0.6941 0.1255];
            app.TSHarnessLabel.Position = [207 9 448 42];
            app.TSHarnessLabel.Text = '';

            % Create SelectModelUnderTestButton
            app.SelectModelUnderTestButton = uibutton(app.GenHarnessTab, 'push');
            app.SelectModelUnderTestButton.ButtonPushedFcn = app.createCallbackFcn(@SelectModelUnderTestButtonPushed, true);
            app.SelectModelUnderTestButton.BackgroundColor = [0.149 0.149 0.149];
            app.SelectModelUnderTestButton.FontWeight = 'bold';
            app.SelectModelUnderTestButton.FontColor = [0.9294 0.6941 0.1255];
            app.SelectModelUnderTestButton.Tooltip = {'点击选择被测的单元模型'};
            app.SelectModelUnderTestButton.Position = [380 305 79 69];
            app.SelectModelUnderTestButton.Text = {'Select '; 'Model'; 'Under'; 'Test'};

            % Create Tree
            app.ModelTree = uitree(app.GenHarnessTab);
            app.ModelTree.FontSize = 13;
            app.ModelTree.FontColor = [0.9294 0.6941 0.1255];
            app.ModelTree.BackgroundColor = [0 0 0];
            app.ModelTree.Position = [11 185 344 187];

            % Create DesignModelsNode
            app.DesignModelsNode = uitreenode(app.ModelTree);
            app.DesignModelsNode.Text = 'Design Models';

            % Create TopModelCheckBox
            app.TopModelCheckBox = uicheckbox(app.GenHarnessTab);
            app.TopModelCheckBox.Tooltip = {'目前需要手动在这里指定选中中的模型是否为顶层模型，还是作为一个model reference被其他模型引用'};
            app.TopModelCheckBox.Text = 'Top Model';
            app.TopModelCheckBox.FontColor = [0.9294 0.6941 0.1255];
            app.TopModelCheckBox.Position = [381 274 77 22];

            % Create DefaultSampleTimeLabel
            app.DefaultSampleTimeLabel = uilabel(app.GenHarnessTab);
            app.DefaultSampleTimeLabel.HorizontalAlignment = 'right';
            app.DefaultSampleTimeLabel.FontColor = [0.9294 0.6941 0.1255];
            app.DefaultSampleTimeLabel.Position = [373 245 63 22];
            app.DefaultSampleTimeLabel.Text = 'Default DT';

            % Create DefaultDTEditField
            app.DefaultSampleTimeEditField = uieditfield(app.GenHarnessTab, 'numeric');
            app.DefaultSampleTimeEditField.HorizontalAlignment = 'center';
            app.DefaultSampleTimeEditField.FontColor = [0.9294 0.6941 0.1255];
            app.DefaultSampleTimeEditField.BackgroundColor = [0 0 0];
            app.DefaultSampleTimeEditField.Tooltip = {'如果被测模型没有显性指定sample time，即配置中的sample是auto，则需要在这里给出默认的测试用例的sample time'};
            app.DefaultSampleTimeEditField.Position = [380 222 79 22];

            % Create ImportTestTab
            app.ImportTestTab = uitab(app.MainTabGroup);
            app.ImportTestTab.AutoResizeChildren = 'off';
            app.ImportTestTab.Title = 'Import Test';

            % Create ExcelFileListLabel
            app.ExcelFileListLabel = uilabel(app.ImportTestTab);
            app.ExcelFileListLabel.FontColor = [0.9294 0.6941 0.1255];
            app.ExcelFileListLabel.Position = [25 352 88 22];
            app.ExcelFileListLabel.Text = 'Test Case FIles';

            % Create OpenExcelFolderButton
            app.OpenExcelFolderButton = uibutton(app.ImportTestTab, 'push');
            app.OpenExcelFolderButton.ButtonPushedFcn = app.createCallbackFcn(@OpenExcelFolderButtonPushed, true);
            app.OpenExcelFolderButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenExcelFolderButton.FontWeight = 'bold';
            app.OpenExcelFolderButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenExcelFolderButton.Tooltip = {'打开Excel'};
            app.OpenExcelFolderButton.Position = [269 352 92 22];
            app.OpenExcelFolderButton.Text = 'Open';

            % Create ExcelFileListBox
            app.ExcelFileListBox = uilistbox(app.ImportTestTab);
            app.ExcelFileListBox.Items = {};
            app.ExcelFileListBox.ValueChangedFcn = app.createCallbackFcn(@ListBoxValueChanged, true);
            app.ExcelFileListBox.FontColor = [1 1 1];
            app.ExcelFileListBox.BackgroundColor = [0.502 0.502 0.502];
            app.ExcelFileListBox.Position = [23 259 238 87];
            app.ExcelFileListBox.Value = {};

            % Create RemoveSelectedTestCaseButton
            app.RemoveSelectedTestCaseButton = uibutton(app.ImportTestTab, 'push');
            app.RemoveSelectedTestCaseButton.ButtonPushedFcn = app.createCallbackFcn(@RemoveSelectedTestCaseButtonPushed, true);
            app.RemoveSelectedTestCaseButton.BackgroundColor = [0.6392 0.3294 0.1333];
            app.RemoveSelectedTestCaseButton.FontColor = [1 1 1];
            app.RemoveSelectedTestCaseButton.Enable = 'off';
            app.RemoveSelectedTestCaseButton.Tooltip = {'删除Excel文件'};
            app.RemoveSelectedTestCaseButton.Position = [191 352 70 22];
            app.RemoveSelectedTestCaseButton.Text = 'Remove';

            % Create OpenExcelInButton
            app.OpenExcelInButton = uibutton(app.ImportTestTab, 'push');
            app.OpenExcelInButton.ButtonPushedFcn = app.createCallbackFcn(@OpenExcelInButtonPushed, true);
            app.OpenExcelInButton.BackgroundColor = [0.6392 0.3294 0.1333];
            app.OpenExcelInButton.FontColor = [1 1 1];
            app.OpenExcelInButton.Enable = 'off';
            app.OpenExcelInButton.Tooltip = {'添加Excel文件'};
            app.OpenExcelInButton.Position = [115 352 70 22];
            app.OpenExcelInButton.Text = 'Add';

            % Create UpdateTestFileButton
            app.UpdateTestFileButton = uibutton(app.ImportTestTab, 'push');
            app.UpdateTestFileButton.ButtonPushedFcn = app.createCallbackFcn(@UpdateTestFileButtonPushed, true);
            app.UpdateTestFileButton.BackgroundColor = [0.502 0.502 0.502];
            app.UpdateTestFileButton.FontColor = [0.9294 0.6941 0.1255];
            app.UpdateTestFileButton.Tooltip = {'导入选中的Excel测试用例，更新Harness模型数据'};
            app.UpdateTestFileButton.Position = [269 305 92 41];
            app.UpdateTestFileButton.Text = {'Update'; 'test case file'};

            % Create ImportAllTestFilesButton
            app.ImportAllTestFilesButton = uibutton(app.ImportTestTab, 'push');
            app.ImportAllTestFilesButton.ButtonPushedFcn = app.createCallbackFcn(@ImportAllTestFilesButtonPushed, true);
            app.ImportAllTestFilesButton.BackgroundColor = [0.502 0.502 0.502];
            app.ImportAllTestFilesButton.FontColor = [0.9294 0.6941 0.1255];
            app.ImportAllTestFilesButton.Enable = 'off';
            app.ImportAllTestFilesButton.Tooltip = {'导入所有的Excel测试用例，更新Harness模型数据'};
            app.ImportAllTestFilesButton.Position = [269 259 92 41];
            app.ImportAllTestFilesButton.Text = {'Import all'; ' test case files'};

            % Create WritebackTestVectorsButton
            app.WritebackTestVectorsButton = uibutton(app.ImportTestTab, 'push');
            app.WritebackTestVectorsButton.ButtonPushedFcn = app.createCallbackFcn(@WritebackTestVectorsButtonPushed, true);
            app.WritebackTestVectorsButton.BackgroundColor = [0.502 0.502 0.502];
            app.WritebackTestVectorsButton.FontColor = [0.9608 0.8078 0.3569];
            app.WritebackTestVectorsButton.Tooltip = {'将Signal Editor中的测试向量写回Excel'};
            app.WritebackTestVectorsButton.Position = [463 257 105 36];
            app.WritebackTestVectorsButton.Text = {'Write back Test'; 'Vectors to Excel'};

            % Create OpenSignalEditorButton
            app.OpenSignalEditorButton = uibutton(app.ImportTestTab, 'push');
            app.OpenSignalEditorButton.ButtonPushedFcn = app.createCallbackFcn(@OpenSignalEditorButtonPushed, true);
            app.OpenSignalEditorButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenSignalEditorButton.FontColor = [0.9608 0.8078 0.3569];
            app.OpenSignalEditorButton.Tooltip = {'点击打开Simulink Signal Editor界面'};
            app.OpenSignalEditorButton.Position = [463 339 192 35];
            app.OpenSignalEditorButton.Text = 'Open Signal Editor';

            % Create WritebackModeDropDown
            app.WritebackModeDropDown = uidropdown(app.ImportTestTab);
            app.WritebackModeDropDown.Items = {'Select Case'};
            app.WritebackModeDropDown.ValueChangedFcn = app.createCallbackFcn(@WritebackModeDropDownValueChanged, true);
            app.WritebackModeDropDown.Tooltip = {'选择要回写Excel的测试用例'};
            app.WritebackModeDropDown.FontColor = [1 1 1];
            app.WritebackModeDropDown.BackgroundColor = [0 0 0];
            app.WritebackModeDropDown.Position = [463 306 192 22];
            app.WritebackModeDropDown.Value = 'Select Case';

            % Create OpenExcelInInputButton_DryRun
            app.OpenExcelInInputButton_DryRun = uibutton(app.ImportTestTab, 'push');
            app.OpenExcelInInputButton_DryRun.ButtonPushedFcn = app.createCallbackFcn(@OpenExcelInInputButton_DryRunPushed, true);
            app.OpenExcelInInputButton_DryRun.BackgroundColor = [0.149 0.149 0.149];
            app.OpenExcelInInputButton_DryRun.FontWeight = 'bold';
            app.OpenExcelInInputButton_DryRun.FontColor = [0.9294 0.6941 0.1255];
            app.OpenExcelInInputButton_DryRun.Tooltip = {'将MATLAB的当前目录定位到模型目录'};
            app.OpenExcelInInputButton_DryRun.Position = [368 352 88 22];
            app.OpenExcelInInputButton_DryRun.Text = 'model folder';

            % Create OpenExcelInOutputButton_DryRun
            app.OpenExcelInOutputButton_DryRun = uibutton(app.ImportTestTab, 'push');
            app.OpenExcelInOutputButton_DryRun.ButtonPushedFcn = app.createCallbackFcn(@OpenExcelInOutputButton_DryRunPushed, true);
            app.OpenExcelInOutputButton_DryRun.BackgroundColor = [0.149 0.149 0.149];
            app.OpenExcelInOutputButton_DryRun.FontWeight = 'bold';
            app.OpenExcelInOutputButton_DryRun.FontColor = [0.9294 0.6941 0.1255];
            app.OpenExcelInOutputButton_DryRun.Tooltip = {'将MATLAB的当前路径定位到模型的测试目录'};
            app.OpenExcelInOutputButton_DryRun.Position = [368 325 88 22];
            app.OpenExcelInOutputButton_DryRun.Text = 'test folder';

            % Create IgnoreDataTypeCheckBox
            app.IgnoreDataTypeCheckBox = uicheckbox(app.ImportTestTab);
            app.IgnoreDataTypeCheckBox.Text = 'Ignore DT';
            app.IgnoreDataTypeCheckBox.FontColor = [0.9294 0.6941 0.1255];
            app.IgnoreDataTypeCheckBox.Position = [580 264 75 22];

            % Create ImportTestTabGroup
            app.ImportTestTabGroup = uitabgroup(app.ImportTestTab);
            app.ImportTestTabGroup.Position = [19 15 642 225];

            % Create CreateRBTFileTab
            app.CreateRBTFileTab = uitab(app.ImportTestTabGroup);
            app.CreateRBTFileTab.Title = 'Create RBT testfile';

            % Create CreateTestFileButton
            app.CreateTestFileButton = uibutton(app.CreateRBTFileTab, 'push');
            app.CreateTestFileButton.ButtonPushedFcn = app.createCallbackFcn(@createTestFileButtonPushed, true);
            app.CreateTestFileButton.BackgroundColor = [0.502 0.502 0.502];
            app.CreateTestFileButton.FontName = 'Arial';
            app.CreateTestFileButton.FontSize = 14;
            app.CreateTestFileButton.FontWeight = 'bold';
            app.CreateTestFileButton.FontAngle = 'italic';
            app.CreateTestFileButton.FontColor = [0.9294 0.6941 0.1255];
            app.CreateTestFileButton.Tooltip = {'创建基于Excel的Simulink Test测试文件。'};
            app.CreateTestFileButton.Position = [402 60 179 100];
            app.CreateTestFileButton.Text = {'Create Testfile for'; 'Requirement Based Test'};

            % Create AuthorNameLabel
            app.AuthorNameLabel = uilabel(app.CreateRBTFileTab);
            app.AuthorNameLabel.HorizontalAlignment = 'right';
            app.AuthorNameLabel.Position = [398 23 76 22];
            app.AuthorNameLabel.Text = 'Author Name';

            % Create AuthorNameEditField
            app.AuthorNameEditField = uieditfield(app.CreateRBTFileTab, 'text');
            app.AuthorNameEditField.HorizontalAlignment = 'center';
            app.AuthorNameEditField.Position = [486 23 100 22];

            % Create ImportedRequirementBasedTestCaseListListBox_2Label
            app.ImportedTestCaseListLabel = uilabel(app.CreateRBTFileTab);
            app.ImportedTestCaseListLabel.HorizontalAlignment = 'center';
            app.ImportedTestCaseListLabel.FontWeight = 'bold';
            app.ImportedTestCaseListLabel.FontColor = [0.9294 0.6941 0.1255];
            app.ImportedTestCaseListLabel.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.ImportedTestCaseListLabel.Position = [96 158 246 28];
            app.ImportedTestCaseListLabel.Text = {'Imported Requirement Based'; ' Test Case List'};

            % Create ImportedRequirementBasedTestCaseListListBox
            app.ImportedTestCaseListBox = uilistbox(app.CreateRBTFileTab);
            app.ImportedTestCaseListBox.Items = {'List all cases'};
            app.ImportedTestCaseListBox.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.ImportedTestCaseListBox.FontColor = [0.4667 0.6745 0.1882];
            app.ImportedTestCaseListBox.BackgroundColor = [0.502 0.502 0.502];
            app.ImportedTestCaseListBox.Position = [94 32 248 121];
            app.ImportedTestCaseListBox.Value = 'List all cases';

            % Create RemoveSelectedTestCaseButton
            app.RemoveSelectedTestCaseButton = uibutton(app.CreateRBTFileTab, 'push');
            app.RemoveSelectedTestCaseButton.ButtonPushedFcn = app.createCallbackFcn(@RemoveSelectedTestCaseFromListButtonPushed, true);
            app.RemoveSelectedTestCaseButton.Position = [18 80 66 50];
            app.RemoveSelectedTestCaseButton.Text = {'Remove'; 'Selected'; 'TestCase'};

            % Create RemoveAllTestCasesButton
            app.RemoveAllTestCasesButton = uibutton(app.CreateRBTFileTab, 'push');
            app.RemoveAllTestCasesButton.ButtonPushedFcn = app.createCallbackFcn(@RemoveAllTestCasesButtonPushed, true);
            app.RemoveAllTestCasesButton.Position = [19 40 66 36];
            app.RemoveAllTestCasesButton.Text = {'Remove'; 'All'};

            % Create DryRunTab
            app.DryRunTab = uitab(app.ImportTestTabGroup);
            app.DryRunTab.Title = 'Dry Run';

            % Create AvailableTestCasesLabel
            app.AvailableTestCasesLabel = uilabel(app.DryRunTab);
            app.AvailableTestCasesLabel.HorizontalAlignment = 'center';
            app.AvailableTestCasesLabel.FontWeight = 'bold';
            app.AvailableTestCasesLabel.FontColor = [0.9294 0.6941 0.1255];
            app.AvailableTestCasesLabel.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.AvailableTestCasesLabel.Position = [67 165 173 28];
            app.AvailableTestCasesLabel.Text = {'Imported Requirement Based'; ' Test Case List'};

            % Create AvailableTestCasesListBox
            app.AvailableTestCasesListBox = uilistbox(app.DryRunTab);
            app.AvailableTestCasesListBox.Items = {'List all cases'};
            app.AvailableTestCasesListBox.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.AvailableTestCasesListBox.FontColor = [0.4667 0.6745 0.1882];
            app.AvailableTestCasesListBox.BackgroundColor = [0.502 0.502 0.502];
            app.AvailableTestCasesListBox.Position = [27 58 254 103];
            app.AvailableTestCasesListBox.Value = 'List all cases';

            % Create SelectedDryRunCasesLabel
            app.SelectedDryRunCasesLabel = uilabel(app.DryRunTab);
            app.SelectedDryRunCasesLabel.HorizontalAlignment = 'center';
            app.SelectedDryRunCasesLabel.FontWeight = 'bold';
            app.SelectedDryRunCasesLabel.FontColor = [0.9294 0.6941 0.1255];
            app.SelectedDryRunCasesLabel.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.SelectedDryRunCasesLabel.Position = [354 168 255 28];
            app.SelectedDryRunCasesLabel.Text = {'Selected '; 'DryRun Test Cases'};

            % Create SelectedDryRunCasesListBox
            app.SelectedDryRunCasesListBox = uilistbox(app.DryRunTab);
            app.SelectedDryRunCasesListBox.Items = {'List selected case(s)'};
            app.SelectedDryRunCasesListBox.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.SelectedDryRunCasesListBox.FontWeight = 'bold';
            app.SelectedDryRunCasesListBox.FontColor = [0.851 0.3255 0.098];
            app.SelectedDryRunCasesListBox.BackgroundColor = [0.502 0.502 0.502];
            app.SelectedDryRunCasesListBox.Position = [354 59 255 103];
            app.SelectedDryRunCasesListBox.Value = 'List selected case(s)';

            % Create MoveRightButton
            app.MoveRightButton = uibutton(app.DryRunTab, 'push');
            app.MoveRightButton.ButtonPushedFcn = app.createCallbackFcn(@MoveRightButtonPushed, true);
            app.MoveRightButton.BackgroundColor = [0.149 0.149 0.149];
            app.MoveRightButton.FontWeight = 'bold';
            app.MoveRightButton.FontColor = [1 1 1];
            app.MoveRightButton.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.MoveRightButton.Position = [293 147 46 22];
            app.MoveRightButton.Text = '>';

            % Create MoveLeftButton
            app.MoveLeftButton = uibutton(app.DryRunTab, 'push');
            app.MoveLeftButton.ButtonPushedFcn = app.createCallbackFcn(@MoveLeftButtonPushed, true);
            app.MoveLeftButton.BackgroundColor = [0.149 0.149 0.149];
            app.MoveLeftButton.FontWeight = 'bold';
            app.MoveLeftButton.FontColor = [1 1 1];
            app.MoveLeftButton.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.MoveLeftButton.Position = [293 118 46 22];
            app.MoveLeftButton.Text = '<';

            % Create MoveAllRightButton
            app.MoveAllRightButton = uibutton(app.DryRunTab, 'push');
            app.MoveAllRightButton.ButtonPushedFcn = app.createCallbackFcn(@MoveAllRightButtonPushed, true);
            app.MoveAllRightButton.BackgroundColor = [0.149 0.149 0.149];
            app.MoveAllRightButton.FontWeight = 'bold';
            app.MoveAllRightButton.FontColor = [1 1 1];
            app.MoveAllRightButton.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.MoveAllRightButton.Position = [293 90 46 22];
            app.MoveAllRightButton.Text = '>>';

            % Create MoveAllLeftButton
            app.MoveAllLeftButton = uibutton(app.DryRunTab, 'push');
            app.MoveAllLeftButton.ButtonPushedFcn = app.createCallbackFcn(@MoveAllLeftButtonPushed, true);
            app.MoveAllLeftButton.BackgroundColor = [0.149 0.149 0.149];
            app.MoveAllLeftButton.FontWeight = 'bold';
            app.MoveAllLeftButton.FontColor = [1 1 1];
            app.MoveAllLeftButton.Tooltip = {'从测试用例清单中选择试运行的测试用例。'};
            app.MoveAllLeftButton.Position = [293 62 46 22];
            app.MoveAllLeftButton.Text = '<<';

            % Create DryRunSelectedCasesButton
            app.DryRunSelectedCasesButton = uibutton(app.DryRunTab, 'push');
            app.DryRunSelectedCasesButton.ButtonPushedFcn = app.createCallbackFcn(@DryRunSelectedCasesButtonPushed, true);
            app.DryRunSelectedCasesButton.BackgroundColor = [0.502 0.502 0.502];
            app.DryRunSelectedCasesButton.FontWeight = 'bold';
            app.DryRunSelectedCasesButton.Tooltip = {'试运行测试用例，查看测试结果'};
            app.DryRunSelectedCasesButton.Position = [50 18 154 31];
            app.DryRunSelectedCasesButton.Text = 'Dry Run Selected Cases';

            % Create WriteBackDryRunResultButton
            app.WriteBackDryRunResultButton = uibutton(app.DryRunTab, 'push');
            app.WriteBackDryRunResultButton.ButtonPushedFcn = app.createCallbackFcn(@WriteBackDryRunResultButtonPushed, true);
            app.WriteBackDryRunResultButton.BackgroundColor = [0.502 0.502 0.502];
            app.WriteBackDryRunResultButton.Enable = 'off';
            app.WriteBackDryRunResultButton.Tooltip = {'将试运行测试用例的结果写回到Excel，作为测试向量的期望输出。'};
            app.WriteBackDryRunResultButton.Position = [483 15 124 36];
            app.WriteBackDryRunResultButton.Text = {'Wrtie Back  DryRun '; 'Result to Excel'};

            % Create Enablewriteback
            app.EnableWritebackCheckBox = uicheckbox(app.DryRunTab);
            app.EnableWritebackCheckBox.ValueChangedFcn = app.createCallbackFcn(@EnablewritebackValueChanged, true);
            app.EnableWritebackCheckBox.Text = {'Enable write back simulation result to Excel'; 'for Signal Editor based test case(s)'};
            app.EnableWritebackCheckBox.FontColor = [0.9294 0.6941 0.1255];
            app.EnableWritebackCheckBox.Position = [219 19 255 28];

            % Create verifyLLRTab
            app.VerifyLLRTab = uitab(app.MainTabGroup);
            app.VerifyLLRTab.Title = 'verify LLR';

            % Create LLRVerificationAxes
            app.LLRVerificationAxes = uiaxes(app.VerifyLLRTab);
            app.LLRVerificationAxes.Toolbar.Visible = 'off';
            app.LLRVerificationAxes.XColor = [1 1 1];
            app.LLRVerificationAxes.YColor = [1 1 1];
            app.LLRVerificationAxes.ZColor = [1 1 1];
            app.LLRVerificationAxes.Color = [0 0 0];
            app.LLRVerificationAxes.MinorGridColor = [1 1 1];
            app.LLRVerificationAxes.ColorOrder = [0.3882 0.8314 0.0706;1 0 0;0.651 0.651 0.651;0.9294 0.6902 0.1294;0.4667 0.6745 0.1882;0.302 0.7451 0.9333;0.6353 0.0784 0.1843];
            app.LLRVerificationAxes.FontSize = 13;
            app.LLRVerificationAxes.Visible = 'off';
            app.LLRVerificationAxes.Position = [166 23 482 336];

            % Create VerifyModelToHLRButton
            app.VerifyModelToHLRButton = uibutton(app.VerifyLLRTab, 'push');
            app.VerifyModelToHLRButton.ButtonPushedFcn = app.createCallbackFcn(@VerifyModelToHLRButtonPushed, true);
            app.VerifyModelToHLRButton.BackgroundColor = [0.502 0.502 0.502];
            app.VerifyModelToHLRButton.FontColor = [0.9294 0.6941 0.1255];
            app.VerifyModelToHLRButton.Tooltip = {'运行来自Excel测试用例的基于需求的测试'};
            app.VerifyModelToHLRButton.Position = [32 248 122 111];
            app.VerifyModelToHLRButton.Text = {'Verify'; 'model (HLR) to'; 'high level'; 'requirements'};

            % Create OpenLLRTestReportButton
            app.OpenLLRTestReportButton = uibutton(app.VerifyLLRTab, 'push');
            app.OpenLLRTestReportButton.ButtonPushedFcn = app.createCallbackFcn(@OpenTestReportButtonPushed2, true);
            app.OpenLLRTestReportButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenLLRTestReportButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenLLRTestReportButton.Tooltip = {'（创建并）打开测试报告'};
            app.OpenLLRTestReportButton.Position = [32 172 122 40];
            app.OpenLLRTestReportButton.Text = 'Open Test Report';

            % Create OpenLLRCoverageReportButton
            app.OpenLLRCoverageReportButton = uibutton(app.VerifyLLRTab, 'push');
            app.OpenLLRCoverageReportButton.ButtonPushedFcn = app.createCallbackFcn(@OpenLLRCoverageReportButtonPushed, true);
            app.OpenLLRCoverageReportButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenLLRCoverageReportButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenLLRCoverageReportButton.Tooltip = {'打开测试覆盖度报告'};
            app.OpenLLRCoverageReportButton.Position = [32 91 122 40];
            app.OpenLLRCoverageReportButton.Text = {'Open Coverage'; 'Report'};

            % Create Lamp
            app.LLRReadyLamp = uilamp(app.VerifyLLRTab);
            app.LLRReadyLamp.Position = [83 220 20 20];
            app.LLRReadyLamp.Color = [0 0 0];

            % Create LLRTestLamp
            app.LLRTestLamp = uilamp(app.VerifyLLRTab);
            app.LLRTestLamp.Position = [83 141 20 20];
            app.LLRTestLamp.Color = [0 0 0];

            % Create LLRCoverageLamp
            app.LLRCoverageLamp = uilamp(app.VerifyLLRTab);
            app.LLRCoverageLamp.Position = [83 61 20 20];
            app.LLRCoverageLamp.Color = [0 0 0];

            % Create genLLTestTab
            app.GenLLTestTab = uitab(app.MainTabGroup);
            app.GenLLTestTab.Title = 'gen LL Test';

            % Create TestGenerationAxes
            app.TestGenerationAxes = uiaxes(app.GenLLTestTab);
            app.TestGenerationAxes.Toolbar.Visible = 'off';
            app.TestGenerationAxes.AmbientLightColor = 'none';
            app.TestGenerationAxes.XColor = [1 1 1];
            app.TestGenerationAxes.YColor = [1 1 1];
            app.TestGenerationAxes.ZColor = [1 1 1];
            app.TestGenerationAxes.BoxStyle = 'full';
            app.TestGenerationAxes.LineWidth = 0.01;
            app.TestGenerationAxes.Color = 'none';
            app.TestGenerationAxes.GridColor = 'none';
            app.TestGenerationAxes.MinorGridColor = [1 1 1];
            app.TestGenerationAxes.ColorOrder = [0.9294 0.6941 0.1255;1 0 0;0.651 0.651 0.651;0.9294 0.6902 0.1294;0.4667 0.6745 0.1882;0.302 0.7451 0.9333;0.6353 0.0784 0.1843];
            app.TestGenerationAxes.FontSize = 13;
            app.TestGenerationAxes.Interruptible = 'off';
            app.TestGenerationAxes.Visible = 'off';
            app.TestGenerationAxes.Position = [16 101 644 252];

            % Create ConfigureTestGenerationButton
            app.ConfigureTestGenerationButton = uibutton(app.GenLLTestTab, 'push');
            app.ConfigureTestGenerationButton.ButtonPushedFcn = app.createCallbackFcn(@ConfigureTestGenerationButtonPushed, true);
            app.ConfigureTestGenerationButton.BackgroundColor = [0.502 0.502 0.502];
            app.ConfigureTestGenerationButton.FontColor = [0.9294 0.6941 0.1255];
            app.ConfigureTestGenerationButton.Tooltip = {'若基于高层需求的测试覆盖度不足100%，则可通过生成low lever test来补足模型的覆盖度。'};
            app.ConfigureTestGenerationButton.Position = [121 16 141 43];
            app.ConfigureTestGenerationButton.Text = {'Generate low-level tests'; 'based on coverage'};

            % Create CurrentCoverageLabel
            app.CurrentCoverageLabel = uilabel(app.GenLLTestTab);
            app.CurrentCoverageLabel.FontSize = 13;
            app.CurrentCoverageLabel.FontColor = [0.9294 0.6941 0.1255];
            app.CurrentCoverageLabel.Position = [16 352 168 25];
            app.CurrentCoverageLabel.Text = 'Current model converage:';

            % Create GenerateTestButton
            app.GenerateTestButton = uibutton(app.GenLLTestTab, 'push');
            app.GenerateTestButton.ButtonPushedFcn = app.createCallbackFcn(@GenerateTestButtonPushed, true);
            app.GenerateTestButton.BackgroundColor = [0.502 0.502 0.502];
            app.GenerateTestButton.FontColor = [0.9294 0.6941 0.1255];
            app.GenerateTestButton.Tooltip = {'为模型运行通过Simulink Design Verifier生成的low level test'};
            app.GenerateTestButton.Position = [409 17 93 43];
            app.GenerateTestButton.Text = {'Verify Model '; 'to LL Tests'};

            % Create GenTestCompleteLamp
            app.GenTestCompleteLamp = uilamp(app.GenLLTestTab);
            app.GenTestCompleteLamp.Position = [299 65 20 20];
            app.GenTestCompleteLamp.Color = [0 0 0];

            % Create GenTestReadyLamp
            app.GenTestReadyLamp = uilamp(app.GenLLTestTab);
            app.GenTestReadyLamp.Position = [446 65 20 20];
            app.GenTestReadyLamp.Color = [0 0 0];

            % Create OpenTestFileButton
            app.OpenTestFileButton = uibutton(app.GenLLTestTab, 'push');
            app.OpenTestFileButton.ButtonPushedFcn = app.createCallbackFcn(@OpenTestFileButtonPushed, true);
            app.OpenTestFileButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenTestFileButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenTestFileButton.Tooltip = {'打开测试用例生成报告'};
            app.OpenTestFileButton.Position = [265 17 88 42];
            app.OpenTestFileButton.Text = {'Open Test '; 'Gen Report'};

            % Create MaxGenerationTimeLabel
            app.MaxGenerationTimeLabel = uilabel(app.GenLLTestTab);
            app.MaxGenerationTimeLabel.HorizontalAlignment = 'right';
            app.MaxGenerationTimeLabel.FontColor = [0.9294 0.6941 0.1255];
            app.MaxGenerationTimeLabel.Position = [18 52 84 22];
            app.MaxGenerationTimeLabel.Text = 'Max Gen Time';

            % Create MaxGenerationTimeEditField
            app.MaxGenerationTimeEditField = uieditfield(app.GenLLTestTab, 'numeric');
            app.MaxGenerationTimeEditField.HorizontalAlignment = 'center';
            app.MaxGenerationTimeEditField.FontColor = [1 1 1];
            app.MaxGenerationTimeEditField.BackgroundColor = [0.149 0.149 0.149];
            app.MaxGenerationTimeEditField.Tooltip = {'允许用于生成测试用例的时间最大值（秒），如果超过该时间，Simulink Design Verifier还未能生成测试用例（例如模型过于复杂），则终止生成测试的过程。'};
            app.MaxGenerationTimeEditField.Position = [27 26 73 22];
            app.MaxGenerationTimeEditField.Value = 300;

            % Create OpenTestHarnessButton
            app.OpenTestHarnessButton = uibutton(app.GenLLTestTab, 'push');
            app.OpenTestHarnessButton.ButtonPushedFcn = app.createCallbackFcn(@OpenTestHarnessButtonPushed, true);
            app.OpenTestHarnessButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenTestHarnessButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenTestHarnessButton.Tooltip = {'打开low level test的测试报告'};
            app.OpenTestHarnessButton.Position = [509 17 72 43];
            app.OpenTestHarnessButton.Text = {'Open LLR '; 'test report'};

            % Create RefreshCoverageButton
            app.RefreshCoverageButton = uibutton(app.GenLLTestTab, 'push');
            app.RefreshCoverageButton.ButtonPushedFcn = app.createCallbackFcn(@RefreshCoverageButtonPushed, true);
            app.RefreshCoverageButton.BackgroundColor = [0.502 0.502 0.502];
            app.RefreshCoverageButton.FontColor = [0.9294 0.6941 0.1255];
            app.RefreshCoverageButton.Tooltip = {'打开low level test的覆盖度报告'};
            app.RefreshCoverageButton.Position = [587 17 74 43];
            app.RefreshCoverageButton.Text = {'Open LLR '; 'cov report'};

            % Create EOCtoHLRTab
            app.EOCtoHLRTab = uitab(app.MainTabGroup);
            app.EOCtoHLRTab.Title = 'EOC to HLR';

            % Create HLRVerificationAxes
            app.HLRVerificationAxes = uiaxes(app.EOCtoHLRTab);
            app.HLRVerificationAxes.Toolbar.Visible = 'off';
            app.HLRVerificationAxes.FontName = 'Arial';
            app.HLRVerificationAxes.FontAngle = 'italic';
            app.HLRVerificationAxes.FontWeight = 'bold';
            app.HLRVerificationAxes.XColor = [1 1 1];
            app.HLRVerificationAxes.YColor = [1 1 1];
            app.HLRVerificationAxes.ZColor = [1 1 1];
            app.HLRVerificationAxes.GridColor = [1 1 1];
            app.HLRVerificationAxes.MinorGridColor = [1 1 1];
            app.HLRVerificationAxes.ColorOrder = [0.3882 0.8314 0.0706;1 0 0;0.651 0.651 0.651;0.9294 0.6902 0.1294;0.4667 0.6745 0.1882;0.302 0.7451 0.9333;0.6353 0.0784 0.1843];
            app.HLRVerificationAxes.FontSize = 14;
            app.HLRVerificationAxes.Visible = 'off';
            app.HLRVerificationAxes.Position = [166 23 482 334];

            % Create VerifyEOCToHLRButton
            app.VerifyEOCToHLRButton = uibutton(app.EOCtoHLRTab, 'push');
            app.VerifyEOCToHLRButton.ButtonPushedFcn = app.createCallbackFcn(@VerifyEOCToHLRButtonPushed, true);
            app.VerifyEOCToHLRButton.BackgroundColor = [0.502 0.502 0.502];
            app.VerifyEOCToHLRButton.FontColor = [0.9294 0.6941 0.1255];
            app.VerifyEOCToHLRButton.Tooltip = {'对代码运行来自Excel测试用例的基于需求的测试'};
            app.VerifyEOCToHLRButton.Position = [27 248 133 111];
            app.VerifyEOCToHLRButton.Text = {'Verify'; 'EOC (SIL)'; 'to High Level'; 'Requirements '};

            % Create OpenHLRTestReportButton
            app.OpenHLRTestReportButton = uibutton(app.EOCtoHLRTab, 'push');
            app.OpenHLRTestReportButton.ButtonPushedFcn = app.createCallbackFcn(@OpenHLRTestReportButtonPushed, true);
            app.OpenHLRTestReportButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenHLRTestReportButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenHLRTestReportButton.Tooltip = {'（创建并）打开测试报告'};
            app.OpenHLRTestReportButton.Position = [32 172 122 40];
            app.OpenHLRTestReportButton.Text = 'Open Test Report';

            % Create OpenHLRCoverageReportButton
            app.OpenHLRCoverageReportButton = uibutton(app.EOCtoHLRTab, 'push');
            app.OpenHLRCoverageReportButton.ButtonPushedFcn = app.createCallbackFcn(@OpenHLRCoverageReportButtonPushed, true);
            app.OpenHLRCoverageReportButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenHLRCoverageReportButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenHLRCoverageReportButton.Tooltip = {'打开测试覆盖度报告'};
            app.OpenHLRCoverageReportButton.Position = [32 91 122 40];
            app.OpenHLRCoverageReportButton.Text = {'Open Coverage'; 'Report'};

            % Create HLRReadyLamp
            app.HLRReadyLamp = uilamp(app.EOCtoHLRTab);
            app.HLRReadyLamp.Position = [83 220 20 20];
            app.HLRReadyLamp.Color = [0 0 0];

            % Create HLRTestLamp
            app.HLRTestLamp = uilamp(app.EOCtoHLRTab);
            app.HLRTestLamp.Position = [83 141 20 20];
            app.HLRTestLamp.Color = [0 0 0];

            % Create HLRCoverageLamp
            app.HLRCoverageLamp = uilamp(app.EOCtoHLRTab);
            app.HLRCoverageLamp.Position = [83 61 20 20];
            app.HLRCoverageLamp.Color = [0 0 0];

            % Create EOCtoLLRTab
            app.EOCtoLLRTab = uitab(app.MainTabGroup);
            app.EOCtoLLRTab.Title = 'EOC to LLR';

            % Create LLREOCVerificationAxes
            app.LLREOCVerificationAxes = uiaxes(app.EOCtoLLRTab);
            app.LLREOCVerificationAxes.Toolbar.Visible = 'off';
            app.LLREOCVerificationAxes.XColor = [1 1 1];
            app.LLREOCVerificationAxes.YColor = [1 1 1];
            app.LLREOCVerificationAxes.ZColor = [1 1 1];
            app.LLREOCVerificationAxes.MinorGridColor = [1 1 1];
            app.LLREOCVerificationAxes.ColorOrder = [0.3882 0.8314 0.0706;1 0 0;0.651 0.651 0.651;0.9294 0.6902 0.1294;0.4667 0.6745 0.1882;0.302 0.7451 0.9333;0.6353 0.0784 0.1843];
            app.LLREOCVerificationAxes.Visible = 'off';
            app.LLREOCVerificationAxes.Position = [166 23 482 336];

            % Create VerifyEOCToLLRButton
            app.VerifyEOCToLLRButton = uibutton(app.EOCtoLLRTab, 'push');
            app.VerifyEOCToLLRButton.ButtonPushedFcn = app.createCallbackFcn(@VerifyEOCToLLRButtonPushed, true);
            app.VerifyEOCToLLRButton.BackgroundColor = [0.502 0.502 0.502];
            app.VerifyEOCToLLRButton.FontColor = [0.9294 0.6941 0.1255];
            app.VerifyEOCToLLRButton.Tooltip = {'对代码运行基于Simulink Design Verifier生成的low level test。'};
            app.VerifyEOCToLLRButton.Position = [27 248 133 111];
            app.VerifyEOCToLLRButton.Text = {'Verify'; 'EOC (SIL)'; 'to Low Level'; 'Requirements '};

            % Create OpenLLREOCTestReportButton
            app.OpenLLREOCTestReportButton = uibutton(app.EOCtoLLRTab, 'push');
            app.OpenLLREOCTestReportButton.ButtonPushedFcn = app.createCallbackFcn(@OpenLLREOCTestReportButtonPushed, true);
            app.OpenLLREOCTestReportButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenLLREOCTestReportButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenLLREOCTestReportButton.Tooltip = {'（创建并）打开测试报告'};
            app.OpenLLREOCTestReportButton.Position = [32 172 122 40];
            app.OpenLLREOCTestReportButton.Text = 'Open Test Report';

            % Create OpenLLREOCCoverageReportButton
            app.OpenLLREOCCoverageReportButton = uibutton(app.EOCtoLLRTab, 'push');
            app.OpenLLREOCCoverageReportButton.ButtonPushedFcn = app.createCallbackFcn(@OpenLLREOCCoverageReportButtonPushed, true);
            app.OpenLLREOCCoverageReportButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenLLREOCCoverageReportButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenLLREOCCoverageReportButton.Tooltip = {'打开测试覆盖度报告'};
            app.OpenLLREOCCoverageReportButton.Position = [32 91 122 40];
            app.OpenLLREOCCoverageReportButton.Text = {'Open Coverage'; 'Report'};

            % Create LLREOCReadyLamp
            app.LLREOCReadyLamp = uilamp(app.EOCtoLLRTab);
            app.LLREOCReadyLamp.Position = [83 220 20 20];
            app.LLREOCReadyLamp.Color = [0 0 0];

            % Create LLREOCTestLamp
            app.LLREOCTestLamp = uilamp(app.EOCtoLLRTab);
            app.LLREOCTestLamp.Position = [83 141 20 20];
            app.LLREOCTestLamp.Color = [0 0 0];

            % Create LLREOCCoverageLamp
            app.LLREOCCoverageLamp = uilamp(app.EOCtoLLRTab);
            app.LLREOCCoverageLamp.Position = [83 61 20 20];
            app.LLREOCCoverageLamp.Color = [0 0 0];

            % Create MergeCovTab
            app.MergeCoverageTab = uitab(app.MainTabGroup);
            app.MergeCoverageTab.Title = 'Merge Cov';

            % Create MILCoverageAxes
            app.MILCoverageAxes = uiaxes(app.MergeCoverageTab);
            app.MILCoverageAxes.Toolbar.Visible = 'off';
            app.MILCoverageAxes.XColor = [1 1 1];
            app.MILCoverageAxes.YColor = [1 1 1];
            app.MILCoverageAxes.ZColor = [1 1 1];
            app.MILCoverageAxes.MinorGridColor = [1 1 1];
            app.MILCoverageAxes.ColorOrder = [0.3882 0.8314 0.0706;1 0 0;0.651 0.651 0.651;0.9294 0.6902 0.1294;0.4667 0.6745 0.1882;0.302 0.7451 0.9333;0.6353 0.0784 0.1843];
            app.MILCoverageAxes.Visible = 'off';
            app.MILCoverageAxes.Position = [17 69 313 253];

            % Create SILCoverageAxes
            app.SILCoverageAxes = uiaxes(app.MergeCoverageTab);
            app.SILCoverageAxes.Toolbar.Visible = 'off';
            app.SILCoverageAxes.XColor = [1 1 1];
            app.SILCoverageAxes.YColor = [1 1 1];
            app.SILCoverageAxes.ZColor = [1 1 1];
            app.SILCoverageAxes.MinorGridColor = [1 1 1];
            app.SILCoverageAxes.ColorOrder = [0.3882 0.8314 0.0706;1 0 0;0.651 0.651 0.651;0.9294 0.6902 0.1294;0.4667 0.6745 0.1882;0.302 0.7451 0.9333;0.6353 0.0784 0.1843];
            app.SILCoverageAxes.Visible = 'off';
            app.SILCoverageAxes.Position = [343 69 313 253];

            % Create MergeModelCoverageButton
            app.MergeModelCoverageButton = uibutton(app.MergeCoverageTab, 'push');
            app.MergeModelCoverageButton.ButtonPushedFcn = app.createCallbackFcn(@MergeModelCoverageButtonPushed2, true);
            app.MergeModelCoverageButton.BackgroundColor = [0.502 0.502 0.502];
            app.MergeModelCoverageButton.FontColor = [0.9294 0.6941 0.1255];
            app.MergeModelCoverageButton.Tooltip = {'合并基于模型测试的覆盖度'};
            app.MergeModelCoverageButton.Position = [83 335 182 34];
            app.MergeModelCoverageButton.Text = 'Merge Model Coverage';

            % Create MergeCodeCoverageButton
            app.MergeCodeCoverageButton = uibutton(app.MergeCoverageTab, 'push');
            app.MergeCodeCoverageButton.ButtonPushedFcn = app.createCallbackFcn(@MergeCodeCoverageButtonPushed, true);
            app.MergeCodeCoverageButton.BackgroundColor = [0.502 0.502 0.502];
            app.MergeCodeCoverageButton.FontColor = [0.9294 0.6941 0.1255];
            app.MergeCodeCoverageButton.Tooltip = {'合并基于代码测试的覆盖度'};
            app.MergeCodeCoverageButton.Position = [410 335 180 34];
            app.MergeCodeCoverageButton.Text = 'Merge Code Coverage';

            % Create OpenMergedMILCoverageButton
            app.OpenMergedMILCoverageButton = uibutton(app.MergeCoverageTab, 'push');
            app.OpenMergedMILCoverageButton.ButtonPushedFcn = app.createCallbackFcn(@OpenMergedMILCoverageButtonPushed, true);
            app.OpenMergedMILCoverageButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenMergedMILCoverageButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenMergedMILCoverageButton.Tooltip = {'运行来自Excel测试用例的基于需求的测试'};
            app.OpenMergedMILCoverageButton.Position = [83 16 182 34];
            app.OpenMergedMILCoverageButton.Text = 'Open Merged MIL Cov Rpt';

            % Create OpenMergedSILCoverageButton
            app.OpenMergedSILCoverageButton = uibutton(app.MergeCoverageTab, 'push');
            app.OpenMergedSILCoverageButton.ButtonPushedFcn = app.createCallbackFcn(@OpenMergedSILCoverageButtonPushed, true);
            app.OpenMergedSILCoverageButton.BackgroundColor = [0.502 0.502 0.502];
            app.OpenMergedSILCoverageButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenMergedSILCoverageButton.Tooltip = {'运行来自Excel测试用例的基于需求的测试'};
            app.OpenMergedSILCoverageButton.Position = [410 17 180 34];
            app.OpenMergedSILCoverageButton.Text = 'Open Merged SIL Cov Rpt';

            % Create RequirementEditorButton
            app.RequirementEditorButton = uibutton(app.MainFigure, 'push');
            app.RequirementEditorButton.ButtonPushedFcn = app.createCallbackFcn(@RequirementEditorButtonPushed, true);
            app.RequirementEditorButton.BackgroundColor = [0.2314 0.2314 0.2314];
            app.RequirementEditorButton.FontColor = [0.9294 0.6941 0.1255];
            app.RequirementEditorButton.Tooltip = {'打开需求编辑界面'};
            app.RequirementEditorButton.Position = [570 642 119 33];
            app.RequirementEditorButton.Text = 'Requirement Editor';

            % Create MessagesLabel
            app.MessagesLabel = uilabel(app.MainFigure);
            app.MessagesLabel.HorizontalAlignment = 'right';
            app.MessagesLabel.FontColor = [1 1 1];
            app.MessagesLabel.Position = [15 189 64 22];
            app.MessagesLabel.Text = 'Messages:';

            % Create MessagesTextArea
            app.MessagesTextArea = uitextarea(app.MainFigure);
            app.MessagesTextArea.Editable = 'off';
            app.MessagesTextArea.FontColor = [1 1 1];
            app.MessagesTextArea.BackgroundColor = [0 0 0];
            app.MessagesTextArea.Position = [18 16 671 174];

            % Create FontSizeSlider
            app.FontSizeSlider = uislider(app.MainFigure);
            app.FontSizeSlider.MajorTicks = [];
            app.FontSizeSlider.FontName = 'Arial';
            app.FontSizeSlider.FontSize = 14;
            app.FontSizeSlider.FontWeight = 'bold';
            app.FontSizeSlider.FontAngle = 'italic';
            app.FontSizeSlider.FontColor = [0.9294 0.6941 0.1255];
            app.FontSizeSlider.Enable = 'off';
            app.FontSizeSlider.Position = [530 199 150 3];

            % Create PleasefirstselectamodelLabel
            app.SelectModelFirstLabel = uilabel(app.MainFigure);
            app.SelectModelFirstLabel.FontSize = 13;
            app.SelectModelFirstLabel.FontWeight = 'bold';
            app.SelectModelFirstLabel.FontAngle = 'italic';
            app.SelectModelFirstLabel.FontColor = [0.9294 0.6941 0.1255];
            app.SelectModelFirstLabel.Position = [33 637 179 42];
            app.SelectModelFirstLabel.Text = 'Please first select a model...';

            % Create OpenExcelInOutputButton
            app.OpenExcelInOutputButton = uibutton(app.MainFigure, 'push');
            app.OpenExcelInOutputButton.ButtonPushedFcn = app.createCallbackFcn(@OpenExcelInOutputButtonPushed, true);
            app.OpenExcelInOutputButton.BackgroundColor = [0.149 0.149 0.149];
            app.OpenExcelInOutputButton.FontWeight = 'bold';
            app.OpenExcelInOutputButton.FontColor = [0.9294 0.6941 0.1255];
            app.OpenExcelInOutputButton.Tooltip = {''};
            app.OpenExcelInOutputButton.Position = [354 642 85 33];
            app.OpenExcelInOutputButton.Text = 'Work Folder';

            % Show the figure after all components are created
            app.MainFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = testAuthoringTool_m

            % Create UIFigure and components
            app.createComponents();

            % Execute the startup routine
            app.startupFcn();
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            if isvalid(app.MainFigure)
                delete(app.MainFigure)
            end
        end
    end
end